son sociales sobre segun que mensajes los logicos esteticos ensayo definicion comunicacion codigos codigo autores c# configuration dependency-injection structuremap application-settings

c# - sociales - Maneras de mantener el código de configuración fuera del código lógico usando Dependency Injection



definicion de codigo segun autores (4)

En mis aplicaciones, hago lo que has hecho anteriormente con IoC. Es decir, tener mi contenedor IoC (StructureMap también) inyectar IApplicationSettings en mis clases.

Por ejemplo, en un proyecto ASP.NET MVC3 puede parecerse a:

Public Class MyController Inherits Controller ... Private ReadOnly mApplicationSettings As IApplicationSettings Public Sub New(..., applicationSettings As IApplicationSettings) ... Me.mApplicationSettings = applicationSettings End Sub Public Function SomeAction(custId As Guid) As ActionResult ... '' Look up setting for custId '' If not found fall back on default like viewModel.SomeProperty = Me.mApplicationSettings.SomeDefaultValue Return View("...", viewModel) End Function End Class

Mi implementación de IApplicationSettings extrae la mayoría de las cosas del archivo .config de la aplicación y también tiene algunos valores codificados.

Mi ejemplo no era el control de flujo lógico (como en el ejemplo), pero de todos modos hubiera funcionado igual.

La otra forma de hacer esto sería hacer un patrón de tipo localizador de servicio, donde le pida a su contenedor de Inyección de Dependencia que le proporcione una instancia de la clase de configuración sobre la marcha. Service-Location se considera un antipatrón en general , pero podría ser útil para usted.

¿Cómo puedo mantener todo el código del archivo de configuración fuera de mi código lógico usando Settings (ApplicationSettingsBase) y Dependency Injection?

Con la configuración me refiero a un archivo de configuración específico del cliente.

¿Realmente tengo que inyectar una clase de configuración cada vez que lo necesito o hay otro patrón?

¡Sería genial obtener un código de muestra!

Muestras:

Configuración estática:

public static class StaticConfiguration { public static bool ShouldApplySpecialLogic { get; set; } public static string SupportedFileMask { get; set; } } public class ConsumerOfStaticConfiguration { public void Process() { if (StaticConfiguration.ShouldApplySpecialLogic) { var strings = StaticConfiguration.SupportedFileMask.Split('',''); foreach (var @string in strings) { } } } }

Configuración no estática:

public interface IConfiguration { bool ShouldApplySpecialLogic { get; set; } string SupportedFileMask { get; set; } } public class Configuration : IConfiguration { public bool ShouldApplySpecialLogic { get; set; } public string SupportedFileMask { get; set; } } public class Consumer { private readonly IConfiguration _configuration; public Consumer(IConfiguration configuration) { _configuration = configuration; } public void Process() { if (_configuration.ShouldApplySpecialLogic) { var strings = _configuration.SupportedFileMask.Split('',''); foreach (var @string in strings) { } } } }

Contexto estático con configuración no estática:

public static class Context { public static IConfiguration Configuration { get; set; } } public class ConsumerOfStaticContext { public void Process() { if (Context.Configuration.ShouldApplySpecialLogic) { var strings = Context.Configuration.SupportedFileMask.Split('',''); foreach (var @string in strings) { } } } }


La parte importante es que la configuración es solo una entre varias fuentes de valores que dirigen el comportamiento de su aplicación.

La segunda opción (configuración no estática) es mejor porque le permite desacoplar por completo al consumidor de la fuente de los valores de configuración . Sin embargo, la interfaz no es necesaria, ya que la configuración de configuración normalmente se modela mejor como Objetos de valor .

Si aún desea leer los valores de un archivo de configuración, puede hacerlo desde la raíz de composición de la aplicación. Con StructureMap, podría ser algo como esto:

var config = (MyConfigurationSection)ConfigurationManager.GetSection("myConfig"); container.Configure(r => r .For<Consumer>() .Ctor<MyConfigurationSection>() .Is(config));


Las clases de configuración reducen la cohesión y aumentan el acoplamiento en los consumidores. Esto se debe a que puede haber muchas configuraciones que no se relacionan con el uno o dos que necesita su clase, pero para cumplir con la dependencia, su implementación de IConfiguration debe proporcionar valores para todos los descriptores, incluso los irrelevantes.

También combina su clase con el conocimiento de la infraestructura: detalles como "estos valores se configuran juntos" se desbordan de la configuración de la aplicación y en sus clases, lo que aumenta el área de superficie afectada por los cambios en los sistemas no relacionados.

La forma menos compleja y más flexible de compartir valores de configuración es usar la inyección de los propios valores por parte del constructor, lo que hace que externalice la infraestructura. Sin embargo, en un comentario sobre otra respuesta, indica que tiene miedo de tener muchos parámetros de constructor, lo cual es una preocupación válida.

El punto clave para reconocer es que no hay diferencia entre dependencias primitivas y complejas. Ya sea que dependas de un número entero o una interfaz, son cosas que no sabes y que deben ser contadas . Desde esta perspectiva, IConfiguration tiene tanto sentido como IDependencies . Los grandes constructores indican que una clase tiene demasiada responsabilidad independientemente de si los parámetros son primitivos o complejos.

Considera tratar int , string y bool como lo harías con cualquier otra dependencia. Hará que sus clases sean más limpias, más centradas, más resistentes al cambio y más fáciles de probar.


Una forma es inyectar una interfaz de configuración como la que publica. Aquí hay un par de otras maneras.

Exponer un Setter

class Consumer { public bool ShouldApplySpecialLogic { get; set; } ... }

En la raíz de la composición, puede leer un archivo de configuración o codificarlo. Ejemplo de Autofac:

builder.RegisterType<Consumer>().AsSelf() .OnActivated(e => e.Instance.ShouldApplySpecialLogic = true);

Esto probablemente solo sea aconsejable cuando tienes un buen valor predeterminado

Inyección de constructor

public class Server { public Server(int portToListenOn) { ... } }

En la raíz de la composición:

builder.Register(c => new Server(12345)).AsSelf();