Ber*_*tie 10 c# configuration inversion-of-control
好吧,我正在进入这个梦幻般的网站,并提出了将配置设置注入应用程序组件的正确方法的问题.因此,概述是:我有一个用C#.Net 3.5编写的应用程序.它由3个程序集组成 - 核心,数据和服务.数据和服务程序集需要从app.config检索的设置,这可以通过设置文件完成,例如.
代码:
public static String RequestQueueConnectionString
{
get { return ConnectionSettings.Default.RequestQueueConnectionString; }
}
Run Code Online (Sandbox Code Playgroud)
配置:
<applicationSettings>
<MyNamespace.Data.ConnectionSettings>
<setting name="RequestQueueConnectionString" serializeAs="String">
...
Run Code Online (Sandbox Code Playgroud)
现在,程序集都是使用StructureMap for IoC进行设置的 - 我认为应该提供我正在寻找的答案,但我只是看不到它!
IoC:
public static void ConfigureStructureMap(IContainer container)
{
container.Configure(x => ...
...
Run Code Online (Sandbox Code Playgroud)
我希望能够做的是注入一个已经填充到IoC容器中的配置类,以便这些设置用于该程序集,而不是设置文件/ app.config中指定的那些设置.所以也许:
public static void ConfigureStructureMap(IContainer container, MyConfigClass config)
{
container.Configure(x => x.For<DataConfig>()
.Singleton()
.Use ???
...
Run Code Online (Sandbox Code Playgroud)
我希望我在这里提供了足够的细节 - 如果我没有,请原谅一个新手,请让我知道还有什么有助于回答这个问题!
因此,经过大量搜索和反复试验后,我收到了 @default.kramer 的链接,我正确地遵循了该链接!再次经过一些尝试和错误(我认为最好的方法),我设法得到了我正在寻找的解决方案。现在,虽然您可以点击链接(我强烈建议这样做),但我将在实施时发布我的问题的解决方案。希望这可以帮助有类似问题的人。
所以,我现在有了我的配置设置类,如下所示:
public static class DispatchConfiguration
{
public static void ConfigureStructureMap(IContainer container, IDispatchConfiguration dispatchConfig)
{
DispatchProcessBatchSize = dispatchConfig.DispatchProcessBatchSize;
ServiceIsActive = dispatchConfig.ServiceIsActive;
...
}
Run Code Online (Sandbox Code Playgroud)
现在,在我使用设置文件从 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);
}
Run Code Online (Sandbox Code Playgroud)
然后在现实世界中我可以从 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;
}
Run Code Online (Sandbox Code Playgroud)
然后实际的配置类如下所示:
[XmlRoot(ElementName = "DispatchSettings", Namespace = "")]
public sealed class DispatchSettings : IDispatchConfiguration
{
public Int32 DispatchProcessBatchSize { get; set; }
public Boolean ServiceIsActive { get; set; }
...
}
Run Code Online (Sandbox Code Playgroud)
为了完整起见,界面如下所示:
public interface IDispatchConfiguration
{
Int32 DispatchProcessBatchSize { get; }
Boolean ServiceIsActive { get; }
...
}
Run Code Online (Sandbox Code Playgroud)
最后,配置文件如下所示:
<?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>
Run Code Online (Sandbox Code Playgroud)
现在,任何目光敏锐的人都会发现“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;
}
}
}
Run Code Online (Sandbox Code Playgroud)
现在你就拥有了!我希望这能让任何有类似问题的人都能解决它,并且足够清楚,可以遵循!