使用Windsor 3从代码中注入AppSettings

时间:2012-06-08 10:56:12

标签: c# castle-windsor windsor-3.0

我正在寻找摆脱Windsor Xml配置文件的方法。我想只留下必要的设置(主要是字符串)并将它们移动到AppSettings。

有没有好方法呢?最好不要在AppSettings和依赖项之间进行手动映射(ctor params)。

我不介意实现这一点,但我想最小化实际业务问题解决应用程序的样板代码。

3 个答案:

答案 0 :(得分:6)

您可以配置dependency on AppSettings

答案 1 :(得分:3)

使用子依赖性解析器注入值

在您发表关于不想注入配置对象的评论之后,我开始查看我的一些SubDependancyResolvers,并且在关闭的情况下,我搜索了如何获取SubDependancyResolver中的属性名称我遇到了一个实际的实现。该项目位于mausch,并由“杂项实验和其他yerbas”组成。我无法验证代码是否有效,但它遵循我的解析器的工作方式。

他们的implementation包含一个属性,您可以将该属性应用于将配置中的应用设置映射到设置属性的设置类。另一种方法是将一个属性应用于要注入构造函数的属性,并一起取消设置类:

public class AppSettingsAttribute: Attribute {}

public class AppSettingsResolver : ISubDependencyResolver
{
private readonly IKernel kernel;

public AppSettingsResolver(IKernel kernel)
{
    this.kernel = kernel;
}

public object Resolve( CreationContext context, ISubDependencyResolver contextHandlerResolver, Castle.Core.ComponentModel model, DependencyModel dependency )
{
    if( (
        from constructor in model.Constructors
        from dependencyModel in constructor.Dependencies
        where dependencyModel == dependency

        from parameterInfo in constructor.Constructor.GetParameters()
        select parameterInfo ).Any( parameterInfo => parameterInfo.Name == dependency.DependencyKey ) )
    {
        var converter = (IConversionManager) kernel.GetSubSystem(SubSystemConstants.ConversionManagerKey);

        return converter.PerformConversion(ConfigurationManager.AppSettings[dependency.DependencyKey], dependency.TargetType);
    }
    return null;
}

public bool CanResolve( CreationContext context, ISubDependencyResolver contextHandlerResolver, Castle.Core.ComponentModel model, DependencyModel dependency )
{
    return (
        from constructor in model.Constructors
        from dependencyModel in constructor.Dependencies
        where dependencyModel == dependency

        from parameterInfo in constructor.Constructor.GetParameters()
        where parameterInfo.Name == dependency.DependencyKey
        select ( Attribute.GetCustomAttribute( parameterInfo, typeof(AppSettingsAttribute) ) != null ) 
    ).FirstOrDefault();
}
}

[ TestFixture ]
public class When_resolving_dependancies_from_the_app_settings_configuration_section
{
    [ Test ]
    public void Should_resolve_a_string_and_an_int()
    {
        var container = new WindsorContainer();

        container.Kernel.Resolver.AddSubResolver(new AppSettingsResolver( container.Kernel ));
        container.Register( Component.For<Dependent>() );

        var dependent = container.Resolve<Dependent>();

        dependent.Foo.Should().Be( "bar" );

        dependent.Baz.Should().Be( 1 );
    }

    public class Dependent
    {
        public string Foo { get; private set; }
        public int Baz { get; private set; }

        public Dependent([AppSettings]string foo, [AppSettings]int baz)
        {
            Foo = foo;
            Baz = baz;
        }
    }
}

答案 2 :(得分:0)

使用具有特定配置类的属性注入

为您的配置创建一个接口,然后让一个实现包装ConfigurationManager.AppSettings,将它作为依赖项注入Windsor。

class SomeThingDependentOnSomeConfiguration
{
    public SomeThingDependentOnSomeConfiguration(ISomeConfiguration config) { ... }
}

interface ISomeConfiguration
{
    int SomeValue { get; }
    string AnotherValue { get; }
}

class SomeConfigurationAppSettings : ISomeConfiguration
{
    public int SomeValue
    {
        get
        {
            return Convert.ToInt32(ConfigurationManager.AppSettings["SomeValue"]);
        }
    }

    public string AnotherValue
    {
        get
        {
            return ConfigurationManager.AppSettings["AnotherValue"];
        }
    }
}

这允许您稍后引入ConfigurationSection(IMO比应用程序设置更清晰),或者您可以将其替换为使用硬编码值的类(如果您需要的话)。

class SomeConfigurationConfigurationSections : ConfigurationSection, ISomeConfiguration
{
    [ConfigurationProperty("SomeValue")]
    public int SomeValue
    {
        get { return (int)this["SomeValue"]; }
    }

    [ConfigurationProperty("AnotherValue")]
    public string AnotherValue
    {
        get { return (string)this["AnotherValue"]; }
    }
}