Dot-Net

在 Bootstrapper 中配置 Automapper 違反了開閉原則?

  • November 27, 2009

我在 Bootstrapper 中配置 AutomapperBootstrap()Application_Start()Bootstrapper. .

你怎麼看,我真的違反了這個原則嗎?

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>();
   }    
}

我認為您違反了兩個原​​則:單一責任原則(SRP)和開放/封閉原則(OCP)。

您違反了 SRP,因為引導類有多個更改原因:如果您更改模型綁定或自動映射器配置。

如果您要添加額外的引導程式碼來配置系統的另一個子組件,您將違反 OCP。

我通常如何處理這個問題是我定義了以下介面。

public interface IGlobalConfiguration
{
   void Configure();
}

對於系統中需要引導的每個組件,我將創建一個實現該介面的類。

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.
   }
}

我使用 Ninject 注入依賴項。IConfiguration是靜態AutoMapper類的底層實現,ModelBinderDictionaryModelBinders.Binder對象。然後,我將定義一個NinjectModule掃描指定程序集的任何實現該IGlobalConfiguration介面的類並將這些類添加到組合中。

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);
   }
}

然後,我會將以下程式碼添加到 Global.asax 文件中。

public class MvcApplication : HttpApplication
{
   public void Application_Start()
   {
       IKernel kernel = new StandardKernel(
           new AutoMapperModule(),
           new MvcModule(),
           new GlobalConfigurationModule()
       );

       Kernel.Get<IGlobalConfiguration>().Configure();
   }
}

現在我的引導程式碼同時遵循 SRP 和 OCP。我可以通過創建一個實現IGlobalConfiguration介面的類來輕鬆添加額外的引導程式碼,而我的全域配置類只有一個改變的理由。

引用自:https://stackoverflow.com/questions/1807298