2011-10-04 19 views
8

Bueno, estoy haciendo mi incursión en este fantástico sitio con una pregunta sobre la forma correcta de inyectar configuraciones en los componentes de la aplicación. Entonces, la visión general es: Tengo una aplicación escrita en C# .Net 3.5. Se compone de 3 conjuntos: un núcleo, un dato y un servicio. Los conjuntos de servicios de datos & requieren configuraciones recuperadas de la aplicación.config, que se realiza a través de un archivo de configuración, por ej.La mejor forma de inyectar la configuración de la aplicación

Código:

public static String RequestQueueConnectionString 
{ 
    get { return ConnectionSettings.Default.RequestQueueConnectionString; } 
} 

Config:

<applicationSettings> 
    <MyNamespace.Data.ConnectionSettings> 
    <setting name="RequestQueueConnectionString" serializeAs="String"> 
    ... 

Ahora, las asambleas son todos de configuración con StructureMap COI - que en mi opinión debe proporcionar la respuesta a lo que estoy buscando, pero ¡Simplemente no puedo verlo!

COI:

public static void ConfigureStructureMap(IContainer container) 
{ 
    container.Configure(x => ... 
    ... 

Lo que yo quiero ser capaz de hacer es inyectar una clase de configuración ya incluido en el contenedor IoC tal que esos valores se utilizan para ese montaje, NO los especificados en el archivo de configuración/app.config. Así que tal vez:

public static void ConfigureStructureMap(IContainer container, MyConfigClass config) 
{ 
    container.Configure(x => x.For<DataConfig>() 
           .Singleton() 
           .Use ??? 
    ... 

espero haber proporcionado suficientes detalles aquí - perdonar a un novato, si no lo he hecho y por favor hágamelo saber qué otra cosa sería útil para responder a esto!

+1

Es posible que desee consultar [esta pregunta] (http://stackoverflow.com/q/7288859/644812). –

Respuesta

3

Por lo tanto, después de mucha búsqueda y prueba y error, me presentaron el enlace de @ default.kramer, que me correspondía. Con un poco de prueba y error, nuevamente (la mejor manera en mi opinión), logré obtener la solución que estaba buscando. Ahora, aunque puede seguir el enlace (y sugeriría encarecidamente que lo haga), voy a publicar la solución a mi pregunta cuando la implementé. Con suerte, esto podría ayudar a alguien con un problema similar.

Por lo tanto, ahora tengo mi clase de instalación de configuración de este modo:

public static class DispatchConfiguration 
{ 
    public static void ConfigureStructureMap(IContainer container, IDispatchConfiguration dispatchConfig) 
    { 
     DispatchProcessBatchSize = dispatchConfig.DispatchProcessBatchSize; 
     ServiceIsActive = dispatchConfig.ServiceIsActive; 
     ... 
    } 

Ahora, antes de que yo estaba usando un archivo de configuración para recuperar la configuración del archivo app.config. Esto fue obviamente bueno para asegurar que tenía flexibilidad para cambiar mi configuración de configuración, pero me dejó el problema de no poder probar fácilmente esa configuración. Digamos que 9/10 pruebas requerían que el servicio estuviera activo, pero 1 prueba quería probar "ServiceIsActive = false;", ahora estoy en problemas.

Ahora, sin embargo, yo soy capaz de inyectar la configuración de la prueba:

[Given(@"Config\.IsServiceActive returns false")] 
public void GivenConfig_IsServiceActiveReturnsFalse() 
{ 
    var settings = new DispatchSettings 
    { 
     ServiceIsActive = false, 
     DispatchProcessBatchSize = 100, 
     UpdatedBy = "Unit Test"  
    }; 

    DispatchConfiguration.ConfigureStructureMap(ObjectFactory.Container, settings); 
} 

Y luego, en el mundo real soy capaz de obtener los ajustes de aplicación.config:

public void Start(String[] args) 
{ 
    var dispatchConfig = this.GetDispatchConfiguration(); 
    DispatchConfiguration.ConfigureStructureMap(ObjectFactory.Container, dispatchConfig); 
    ... 
} 

private IDispatchConfiguration GetDispatchConfiguration() 
{ 
    var config = (DispatchSettings)ConfigurationManager.GetSection("DispatchSettings"); 
    return config; 
} 

Y entonces la clase de configuración actual se parece a:

[XmlRoot(ElementName = "DispatchSettings", Namespace = "")] 
public sealed class DispatchSettings : IDispatchConfiguration 
{ 
    public Int32 DispatchProcessBatchSize { get; set; } 
    public Boolean ServiceIsActive { get; set; } 
    ... 
} 

En aras de la exhaustividad de la interfaz se ve así:

public interface IDispatchConfiguration 
{ 
    Int32 DispatchProcessBatchSize { get; } 
    Boolean ServiceIsActive { get; } 
    ... 
} 

Y por último, las miradas de archivos de configuración de esta manera:

<?xml version="1.0" encoding="utf-8" ?> 
<configuration> 
    <configSections> 
     <section name="DispatchSettings" type="MyNamespace.XmlConfigurator, MyNamespace.Core" /> 
    </configSections> 

    <DispatchSettings type="MyNamespace.DispatchSettings, MyNamespace.Core"> 
     <ServiceIsActive>True</ServiceIsActive> 
     <DispatchProcessBatchSize>100</DispatchProcessBatchSize> 
    </DispatchSettings> 

Ahora, cualquier persona que tenga buen ojo detectará "MyNamespace.XmlConfigurator". Encontré esto en uno de mis viajes a Google, y el código te permite deserializar una configuración Xml en una clase de tu gusto (como se muestra en este ejemplo). Por lo tanto, para asegurarse de tener el código completo para que esta técnica funcione, a continuación se muestra el código del XmlConfigurator. No puedo recordar dónde lo encontré, ¡pero muchas gracias a la persona que lo escribió!

public sealed class XmlConfigurator : IConfigurationSectionHandler 
{ 
    public XmlConfigurator() 
    { 
    } 

    public object Create(object parent, object configContext, XmlNode section) 
    { 
     XPathNavigator navigator = null; 
     String typeName = null; 
     Type sectionType = null; 
     XmlSerializer xs = null; 
     XmlNodeReader reader = null; 

     try 
     { 
      Object settings = null; 

      if (section == null) 
      { 
       return settings; 
      } 

      navigator = section.CreateNavigator(); 
      typeName = (string)navigator.Evaluate("string(@type)"); 
      sectionType = Type.GetType(typeName); 
      xs = new XmlSerializer(sectionType); 
      reader = new XmlNodeReader(section); 

      settings = xs.Deserialize(reader); 

      return settings; 
     } 
     finally 
     { 
      xs = null; 
     } 
    } 
} 

¡Y ya lo tienes! Espero que esto permita que cualquier persona con un problema similar lo resuelva y está lo suficientemente claro como para seguirlo.

Cuestiones relacionadas