私は 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
の基盤となる実装であり、 はオブジェクトです。次に、指定されたアセンブリをスキャンしてインターフェイスを実装するクラスを探し、それらのクラスを複合クラスに追加するを定義します。AutoMapper
ModelBinderDictionary
ModelBinders.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
。グローバル構成クラスを変更する理由は 1 つだけです。