我认为您违反了两个原则:单一责任原则(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
类的底层实现,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
接口的类轻松添加额外的引导代码,而我的全局配置类只有一个更改的理由。