问题描述
我在引导程序配置Automapper,我称之为引导()
在的Application_Start()
,和有人告诉我,这是错误的,因为我每一次我一定要添加一个新的映射来修改我的引导程序
类,所以我违反了开闭原则。
你怎么想,我真的违反这个原则?
公共静态类引导程序
{
公共静态无效的自举()
{
ModelBinders.Binders.DefaultBinder =新MyModelBinder();
InputBuilder.BootStrap();
ConfigureAutoMapper();
}
公共静态无效ConfigureAutoMapper()
{
Mapper.CreateMap<使用者,UserDisplay>()
.ForMember(O => o.UserRolesDescription,
OPT => opt.ResolveUsing&其中; RoleValueResolver>());
Mapper.CreateMap&所述;组织,OrganisationDisplay>();
Mapper.CreateMap&所述;组织,OrganisationOpenDisplay>();
Mapper.CreateMap&所述; OrganisationAddress,OrganisationAddressDisplay>();
}
}
我认为,你违反了两个原则:单一职责原则(SRP)和开/闭原则(OCP)
。正在违反SRP,因为自举类有多个理由去改变。如果你改变模型绑定或自动映射器配置。
您就违反了OCP,如果你要添加额外的引导code,用于配置系统的其他子组件。
我通常如何处理这是我定义如下界面。
公共接口IGlobalConfiguration
{
无效配置();
}
对于系统中的每个组件需要引导我将创建一个实现该接口的类。
公共类AutoMapperGlobalConfiguration:IGlobalConfiguration
{
私人只读的IConfiguration配置;
公共AutoMapperGlobalConfiguration(的IConfiguration配置)
{
this.configuration =配置;
}
公共无效配置()
{
//添加AutoMapper配置在这里。
}
}
公共类ModelBindersGlobalConfiguration:IGlobalConfiguration
{
私人只读ModelBinderDictionary粘合剂;
公共ModelBindersGlobalConfiguration(ModelBinderDictionary粘合剂)
{
this.binders =粘合剂;
}
公共无效配置()
{
//把这里的模型绑定配置。
}
}
我用Ninject注入的依赖。 的IConfiguration
是静态的底层实现 AutoMapper
类和 ModelBinderDictionary
是 ModelBinders.Binder
对象。然后,我会定义一个 NinjectModule
将扫描指定组件实现 IGlobalConfiguration
接口的类并添加这些类到的复合物。
公共类GlobalConfigurationModule:NinjectModule
{
私人只读装配组件;
公共GlobalConfigurationModule()
:这个(Assembly.GetExecutingAssembly()){}
公共GlobalConfigurationModule(装配组装)
{
this.assembly =组装;
}
公众覆盖无效负载()
{
GlobalConfigurationComposite复合=
新GlobalConfigurationComposite();
IEnumerable的<类型>类型=
。assembly.GetExportedTypes()GetTypeOf< IGlobalConfiguration>()
.SkipAnyTypeOf&其中; IComposite&其中; IGlobalConfiguration>>();
的foreach(在类型VAR型)
{
IGlobalConfiguration配置=
(IGlobalConfiguration)Kernel.Get(类型);
composite.Add(配置);
}
绑定< IGlobalConfiguration>()ToConstant(复合)。
}
}
我会再添加以下code到Global.asax文件。
公共类MvcApplication:的HttpApplication
{
公共无效的Application_Start()
{
的iKernel内核=新StandardKernel(
新AutoMapperModule(),
新MvcModule(),
新GlobalConfigurationModule()
);
Kernel.Get< IGlobalConfiguration>()配置()。
}
}
现在我的引导code坚持既SRP和OCP。我可以很容易地创建实现 IGlobalConfiguration
接口和我的全球配置类的类添加额外的引导code只能有一个理由去改变。
I am configuring Automapper in the Bootstrapper and I call the Bootstrap()
in the Application_Start()
, and I've been told that this is wrong because I have to modify my Bootstrapper
class each time I have to add a new mapping, so I am violating the Open-Closed Principle.
How do you think, do I really violate this principle?
public static class Bootstrapper
{
public static void BootStrap()
{
ModelBinders.Binders.DefaultBinder = new MyModelBinder();
InputBuilder.BootStrap();
ConfigureAutoMapper();
}
public static void ConfigureAutoMapper()
{
Mapper.CreateMap<User, UserDisplay>()
.ForMember(o => o.UserRolesDescription,
opt => opt.ResolveUsing<RoleValueResolver>());
Mapper.CreateMap<Organisation, OrganisationDisplay>();
Mapper.CreateMap<Organisation, OrganisationOpenDisplay>();
Mapper.CreateMap<OrganisationAddress, OrganisationAddressDisplay>();
}
}
I would argue that you are violating two principles: the single responsibility principle (SRP) and the open/closed principle (OCP).
You are violating the SRP because the bootstrapping class have more than one reason to change: if you alter model binding or the auto mapper configuration.
You would be violating the OCP if you were to add additional bootstrapping code for configuring another sub-component of the system.
How I usually handle this is that I define the following interface.
public interface IGlobalConfiguration
{
void Configure();
}
For each component in the system that needs bootstrapping I would create a class that implements that interface.
public class AutoMapperGlobalConfiguration : IGlobalConfiguration
{
private readonly IConfiguration configuration;
public AutoMapperGlobalConfiguration(IConfiguration configuration)
{
this.configuration = configuration;
}
public void Configure()
{
// Add AutoMapper configuration here.
}
}
public class ModelBindersGlobalConfiguration : IGlobalConfiguration
{
private readonly ModelBinderDictionary binders;
public ModelBindersGlobalConfiguration(ModelBinderDictionary binders)
{
this.binders = binders;
}
public void Configure()
{
// Add model binding configuration here.
}
}
I use Ninject to inject the dependencies. IConfiguration
is the underlying implementation of the static AutoMapper
class and ModelBinderDictionary
is the ModelBinders.Binder
object. I would then define a NinjectModule
that would scan the specified assembly for any class that implements the IGlobalConfiguration
interface and add those classes to a composite.
public class GlobalConfigurationModule : NinjectModule
{
private readonly Assembly assembly;
public GlobalConfigurationModule()
: this(Assembly.GetExecutingAssembly()) { }
public GlobalConfigurationModule(Assembly assembly)
{
this.assembly = assembly;
}
public override void Load()
{
GlobalConfigurationComposite composite =
new GlobalConfigurationComposite();
IEnumerable<Type> types =
assembly.GetExportedTypes().GetTypeOf<IGlobalConfiguration>()
.SkipAnyTypeOf<IComposite<IGlobalConfiguration>>();
foreach (var type in types)
{
IGlobalConfiguration configuration =
(IGlobalConfiguration)Kernel.Get(type);
composite.Add(configuration);
}
Bind<IGlobalConfiguration>().ToConstant(composite);
}
}
I would then add the following code to the Global.asax file.
public class MvcApplication : HttpApplication
{
public void Application_Start()
{
IKernel kernel = new StandardKernel(
new AutoMapperModule(),
new MvcModule(),
new GlobalConfigurationModule()
);
Kernel.Get<IGlobalConfiguration>().Configure();
}
}
Now my bootstrapping code adheres to both SRP and OCP. I can easily add additional bootstrapping code by creating a class that implements the IGlobalConfiguration
interface and my global configuration classes only have one reason to change.
这篇关于在引导程序配置Automapper违反了开放封闭原则?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!