注入应用配置的最佳方式

本文关键字:最佳 方式 配置 应用 注入 | 更新日期: 2023-09-27 18:10:35

好了,我带着一个关于将配置设置注入应用程序组件的正确方法的问题进入这个奇妙的网站。那么,概述是:我有一个用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 -这在我看来应该提供我正在寻找的答案,但我只是不能完全看到它!

国际奥委会

:

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

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

注入应用配置的最佳方式

所以,经过大量的搜索和尝试和错误,我看到了@default.kramer的链接,我忠实地跟随了它!通过一点点的尝试和错误(在我看来是最好的方法),我设法得到了我一直在寻找的解决方案。现在,虽然你可以按照链接(我强烈建议这样做),我要张贴我的问题的解决方案,因为我实现了它。希望这能帮助到有类似问题的人。

所以,我现在有了我的配置设置类,像这样:
public static class DispatchConfiguration
{
    public static void ConfigureStructureMap(IContainer container, IDispatchConfiguration dispatchConfig)
    {
        DispatchProcessBatchSize = dispatchConfig.DispatchProcessBatchSize;
        ServiceIsActive = dispatchConfig.ServiceIsActive;
        ...
    }

现在,在我使用设置文件从app.config文件中检索配置之前。这显然有利于确保我在更改配置设置时具有灵活性,但它给我留下了无法轻松测试这些设置的问题。假设有9/10个测试要求服务处于活动状态,但有一个测试想要测试"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);
}

然后在现实世界中,我可以从app.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;
}

然后实际的配置类看起来像:

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

现在,任何有敏锐眼睛的人都会发现"mynamspace . 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;
        }
    }
}

你就知道了!我希望这能让任何有类似问题的人解决它,并且足够清晰可循!