Argumentaría que está violando dos principios: el principio de responsabilidad única (SRP) y el principio de apertura/cierre (OCP).
Está violando el SRP porque la clase de arranque tiene más de un motivo para cambiar: si modifica el enlace del modelo o la configuración del asignador automático.
Usted estaría violando el OCP si tuviera que agregar un código de arranque adicional para configurar otro subcomponente del sistema.
Como suelo manejar esto es que defino la siguiente interfaz.
public interface IGlobalConfiguration
{
void Configure();
}
Para cada componente del sistema que necesita un arranque, crearía una clase que implemente esa interfaz.
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.
}
}
Uso Ninject para inyectar las dependencias.IConfiguration
es la implementación subyacente de la clase estática AutoMapper
y ModelBinderDictionary
es el objeto ModelBinders.Binder
. Luego definiría un NinjectModule
que escanearía el ensamblado especificado para cualquier clase que implemente la interfaz IGlobalConfiguration
y agregue esas clases a un compuesto.
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);
}
}
Me gustaría agregar el siguiente código al archivo Global.asax.
public class MvcApplication : HttpApplication
{
public void Application_Start()
{
IKernel kernel = new StandardKernel(
new AutoMapperModule(),
new MvcModule(),
new GlobalConfigurationModule()
);
Kernel.Get<IGlobalConfiguration>().Configure();
}
}
Ahora mi código de arranque se adhiere tanto a SRP como a OCP. Puedo agregar fácilmente código de arranque adicional creando una clase que implementa la interfaz IGlobalConfiguration
y mis clases de configuración global solo tienen un motivo para cambiar.
y todavía tiene que cambiar el Configurar método en AutoMapperGlobalConfiguration cada vez que necesita agregar una nueva asignación – Omu
Pero eso no violaría OCP. OCP no es escribir una vez, nunca volver a tocar. OCP afirma que el consumidor del código de arranque, el GlobalConfigurationModule (GCM), debe confiar en la abstracción y no en la implementación conrete. Si tuviera que agregar bootstrapping para log4net, crearía una clase Log4NetGlobalConfiguration que implementaría IGlobalConfiguration. Sin embargo, no tendría que modificar ninguna otra parte de mi código y definitivamente no el GCM porque no tiene un conocimiento complejo de la implementación conrete de la interfaz IGlobalConfiguration. – mrydengren
Estoy en una duda. Una vez que se ejecuta Mapper.CreateMap <>(), ¿los mapas existen hasta el cierre de la aplicación? – JPCF