¿Cómo se puede mantener todo el archivo de configuración de código de mi lógica de código mediante el uso de la Configuración (ApplicationSettingsBase) y la Inyección de dependencias?

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

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

Sería genial conseguir algún código de ejemplo!

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)
            {

            }
        }
    }
}

No estática Configuración:

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 la no configuración 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)
            {

            }
        }
    }
}
  • lo que queremos es un Contenedor de Inversión de Control
  • lo que quiero es una explicación de separar la lógica de código de configuración mediante el uso de un contenedor de inversión de control.
  • Escribí un post en el blog explicando cómo y por qué las utilizamos StructureMap para mantener nuestra configuración independiente de nuestra lógica: lostechies.com/joshuaflanagan/2009/07/13/… La funcionalidad que se describe en ese puesto ya está disponible en la FubuCore utilidad de la biblioteca (usted lo puede obtener a través de nuget): github.com/DarthFubuMVC/fubucore/tree/master/src/FubuCore/…
InformationsquelleAutor Rookian | 2011-09-02

4 Comentarios

  1. 24

    La parte importante es darse cuenta de que la configuración es sólo una entre varias fuentes de valores que guían su comportamiento de la aplicación.

    La segunda opción (no la configuración estática) es mejor porque permite completamente de disociar el consumo de la fuente de los valores de configuración. Sin embargo, la interfaz no es imprescindible, como opciones de configuración generalmente se modela mejor como Objetos de Valor.

    Si quieres leer los valores de un archivo de configuración, puede hacerlo desde la aplicación La Composición De La Raíz. Con StructureMap, es posible que se ve algo como esto:

    var config = (MyConfigurationSection)ConfigurationManager.GetSection("myConfig");
    
    container.Configure(r => r
        .For<Consumer>()
        .Ctor<MyConfigurationSection>()
        .Is(config));
    • Seeman, mediante su enfoque sería engorroso, porque tengo más de 100 diferentes tipos de consumidores. Así que para todos los consumidores, tengo que configurar mi Coi registro, ¿no?
    • El uso de una convención. Con StructureMap, el punto de entrada es el método de análisis.
    • gracias 🙂 voy a echar un vistazo y pensar acerca de su enfoque.
  2. 29

    Configuración de clases de reducir cohension y aumento de acoplamiento en los consumidores. Esto es porque puede haber muchas opciones que no se relacionan el uno o el dos es necesario por su clase, sin embargo, con el fin de cumplir con la dependencia, la implementación de IConfiguration debe de suministro para todos los valores de los descriptores de acceso, incluso el irrelevantes.

    También las parejas de la clase a la infraestructura de conocimiento: detalles como «estos valores se configuran juntos» sangrar de la configuración de la aplicación y en sus clases, el aumento de la superficie afectada por los cambios de sistemas no relacionados.

    El menos complejo, más flexible manera de compartir los valores de configuración es el uso de inyección de constructor de los valores propios, la externalización de la infraestructura de preocupaciones. Sin embargo, en un comentario en otra respuesta, te indican que tienes miedo de tener un gran número de parámetros del constructor, que es una preocupación válida.

    El punto clave que hay que reconocer es que no hay ninguna diferencia entre el primitivo y el complejo de dependencias. Si usted depende de un número entero o una interfaz, son las dos cosas que no sabe y debe ser contada. Desde esta perspectiva, IConfiguration hace tanto sentido como IDependencies. Grandes constructores indicar que una clase tiene demasiada responsabilidad, independientemente de si los parámetros son simples o complejos.

    Considerar el tratamiento de int, string y bool como lo haría con cualquier otra dependencia. Esto te permitirá hacer tus clases más limpio, más centrado, más resistentes al cambio, y más fáciles de la prueba de unidad.

    • Creo que esta es la mejor respuesta, porque reconoce que las clases no necesitan saber acerca de IConfiguration pero sólo lo que su real de las dependencias. Usted puede tener causa un día para tener dos instancias de una clase configurado de manera diferente. por ejemplo, «¿Cómo cambian los resultados si utilizamos el co-confabulator algoritmo preferido por algunas instalaciones en lugar de a la inversa-hindlebrook preferido por los demás?»
    • ¿Te he derecha, que no desea utilizar un tipo complejo, pero simple de tipos como int, string y bool? Si es así ¿qué pasa si usted tiene 5 diferentes parámetros de configuración y tal vez 2 dependencias. Esto se hinchan su constructor. Tal vez se podría utilizar un determinado tipo de complejo para cada caso en el que usted necesita alguna configuración. Algo así como FileParserConfiguration, BootConfiguration, DatabaseConfiguration. Todavía no estoy seguro de lo que debe usar 🙂
    • Me gustaría ver en que situación como tener 7 dependencias. Como con cualquier clase que tiene un gran número de dependencias, hay algunos refactorización que tiene que pasar para reducir la clase de responsabilidad. Constructor de la hinchazón es un síntoma de una clase que no es demasiado grande; realmente no tiene nada que ver con los valores primitivos.
    • Dicho de otra manera: la agrupación de constructor de valores en virtud de un IConfiguration tipo puede reducir el número de parámetros del constructor, pero no reducir la complejidad, que es el verdadero peligro detrás de constructor de la hinchazón.
    • Estoy de acuerdo con usted que tiene un montón de dependencias es una señal de violar SRP. Pero también es una mala práctica para el uso de los tipos simples en lugar de un tipo complejo. Los tipos simples son malos en mutabilidad. Y creo que tener complejo de cohesiva tipos pueden hacer las cosas más fáciles de entender. Para la agrupación de las cosas en las clases hace que las cosas sean más comprensibles.
    • ¿Usted tiene un de referencia de la que puedo mirar que entra en más detalles acerca de los tipos primitivos de ser una mala práctica? Yo no seguir la línea de razonamiento. Debajo de todas las capas de abstracción de, digamos, un acceso a los datos marco, algunos de clase en algún lugar debe saber una cadena de conexión. Los tipos primitivos deben estar bien oculto, pero usted los necesita en el futuro. Es intuitivo para mí que si la clase Foo sólo se necesita valor, después liando con inusitada, sin relación de los valores de B, C, y D aumenta la complejidad y el acoplamiento con ningún beneficio para Foo. Se acaba de fugas en la infraestructura de conocimiento en Foo.
    • Bueno, en mi caso, los valores están relacionados, ya que todos ellos pertenecen a la categoría de configuración. No todas las propiedades que tiene para ser utilizado dentro de un método. Tiene una mirada en: stackoverflow.com/questions/7324783/… Véase también el libro de Robert C. Martin Código Limpio, el Argumento de los Objetos de la página 43.
    • Estoy de acuerdo en que el argumento de que los objetos son una válida y útil para la agrupación de los valores. El factor clave es la porque se agrupan: la configuración es una técnica de organización de los conceptos, mientras que el argumento de los objetos tienden a orientarse en todo el dominio del problema. Si dos valores son agrupadas solamente porque son configurables, que no son capaces de comunicar su propósito. Si desea agrupar un nombre de host y el puerto, por ejemplo, IServerContext es mucho más expresivo que IConfiguration. La agrupación a favor de la intención sobre el mecanismo.
    • sí creo que debemos tener la misma opinión 🙂 Mi ejemplo es simplemente malo. Pero una pregunta. Usted utilizaría un contexto de configuración exclusiva o elegir la composición utilizando una configuración de la raíz? Así DbConfiguration / PathConfiguration o de Configuración.DbConfiguration / Configuración.PathConfiguration?
    • Yo generalmente aplazar a la composición, ya que se requiere tomar menos decisiones en el punto de uso y por lo tanto resultados en la reducción de acoplamiento.
    • ok, lo he entendido, gracias 😉
    • Otro nombre para la idea de «no uso de los tipos primitivos» es el Primitiva Obsesión código olor. En C++ esto sería tan fácil como un #typedef pero nos C# personas no tienen esa opción. He creado un paquete de NuGet llamado LikeType, que es similar a la typedef en C++ y hace que sea fácil para evitar Primitivo Obsesión.

  3. 2

    Es una forma de inyectar una interfaz de configuración como tú post. Aquí hay un par de otras maneras.

    Exponer un Setter

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

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

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

    Esto es probablemente sólo recomendable cuando se tiene un buen valor por defecto

    Inyección De Constructor

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

    En la composición de la raíz:

    builder.Register(c => new Server(12345)).AsSelf();
    • Me asusta tener una gran cantidad de parámetros del constructor, cuando el uso de inyección de constructor. Setter de inyección de evitar esto, pero a ello se añade un nuevo enfoque de llegar a las dependencias y creo que esto sería más complicado (mezcla de constructor y setter de la inyección.
  4. 0

    En mis aplicaciones, yo hago lo que ustedes han hecho por encima del Coi. Es decir, tener a mi contenedor de IoC (StructureMap también) inyectar una IApplicationSettings en mis clases.

    Por ejemplo, en un ASP.NET MVC3 proyecto, se puede ver como:

    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

    La implementación de mi IApplicationSettings tira de la mayoría de las cosas a partir de la aplicación del .config archivo y tiene un par de valores codificados en allí también.

    Mi ejemplo no era la lógica de control de flujo (como en tu ejemplo), pero que habría trabajado de la misma si lo fue.

    La otra manera de hacer esto sería hacer un servicio localizador tipo de patrón, donde se le solicitarán sus contenedor de Inyección de Dependencia para obtener una instancia de la clase de configuración sobre la marcha. Servicio de Ubicación se considera un anti-patrón general, pero puede ser de utilidad para usted.

    • ¿Qué piensa usted acerca de «Contexto Estático con la no configuración estática»?
    • Parece un probable solución, y evita completamente el DI. Puede que no sea tan «flexible» como sea necesario. Con DI, su Contenedor de IoC puede proporcionar implementaciones diferentes de diferentes clases (si es necesario), donde el uso de la ruta estática que son casi encerrados en una aplicación de la configuración. Puede no ser un problema en tu situación, solo que pensé que me gustaría mencionar.

Dejar respuesta

Please enter your comment!
Please enter your name here