Bootstrapper で Automapper を設定すると、オープンクローズ原則に違反しますか? 質問する

Bootstrapper で Automapper を設定すると、オープンクローズ原則に違反しますか? 質問する

私は Bootstrapper で Automapper を構成し、Bootstrap()で を呼び出していますが、新しいマッピングを追加するたびにクラス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>();
    }    
}

ベストアンサー1

私は、あなたが単一責任原則 (SRP) とオープン/クローズ原則 (OCP) という 2 つの原則に違反していると主張します。

ブートストラップ クラスを変更する理由が複数あるため (モデル バインディングまたは自動マッパー構成を変更する場合など)、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の基盤となる実装であり、 はオブジェクトです。次に、指定されたアセンブリをスキャンしてインターフェイスを実装するクラスを探し、それらのクラスを複合クラスに追加するを定義します。AutoMapperModelBinderDictionaryModelBinders.BinderNinjectModuleIGlobalConfiguration

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。グローバル構成クラスを変更する理由は 1 つだけです。

おすすめ記事