最佳注入应用程序配置

问题描述:

好方式,我正在做我涉足这个奇妙的网站有大约注入配置设置应用程序组件的正确方法问题。所以,概述是:我有一个用C#.Net 3.5编写的应用程序。它由3个组件组成 - 一个核心,一个数据和一个服务。数据&服务组件需要从在app.config,其经由设置文件,例如进行检索设置。最佳注入应用程序配置

代码:

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

配置:

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

现在,组件是用StructureMap的IoC的所有设置 - 这在我看来应该提供答案,我所期待的,但我真的不太明白!

IOC:

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

我希望能够做的就是注入已经填充到IoC容器,使得这些设置将用于所有组件,而不是那些在设置文件中指定的配置类/ app.config。因此,或许:

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

我希望我在这里提供足够的细节 - 原谅一个新手,如果我没有,请让我知道什么是在回答这是很有帮助的!

+1

你可能想看看[这个问题](http://*.com/q/7288859/644812)。 –

所以,很多搜索和反复试验后,我提交了@ default.kramer的链接,这是我duely跟着!再次尝试一下(我认为最好的方式),我设法找到了我所需要的解决方案。现在,虽然你可以按照链接(我会强烈建议这样做),我要解决张贴到我的问题,因为我实现了它。希望这可以帮助有类似问题的人。

所以,我现在有我的配置设置类,像这样:

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

现在,我使用的是设置文件检索配置了app.config文件之前。这显然有利于确保我在改变我的配置设置的灵活性,但它给我留下了不能够方便地测试这些设置的问题。说9/10测试所需的服务,是积极的,但1个测试要考“ServiceIsActive = FALSE;”现在我就麻烦了。

但是现在,我能够从测试注入配置:

[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); 
} 

然后在现实世界中,我能够从应用程序获取设置。配置:

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; 
} 

然后实际的配置类的样子:

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

为了完整起见,界面看起来像这样:

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

最后,配置文件长相像这样:

<?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> 

现在,任何敏锐的眼睛都会发现“MyNamespace.XmlConfigurator”。我在我的一次Google旅程中发现了这种情况,并且代码允许您将Xml配置反序列化为您想要的类(如本例所示)。因此,为了确保您拥有完整的代码来使这项技术发挥作用,以下是XmlConfigurator的代码。我不记得我遇到过的地方,但非常感谢编写它的人!

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; 
     } 
    } 
} 

那里你有它!我希望这可以让任何遇到类似问题的人解决问题,并且足够清楚地遵循!