如何构造函数注入仅在运行时已知的字符串?(温莎城堡)

本文关键字:字符串 城堡 注入 构造函数 运行时 | 更新日期: 2023-09-27 18:34:25

>我有依赖于字符串的类:

public class Person
{
    private readonly string _name;
    public Person(string name)
    {
        if (name == null) throw new ArgumentNullException("name");
        _name = name;
    }
}

这个字符串"name"只在运行时知道,例如。 它在配置中定义。所以我有这个接口提供这个字符串:

public interface IConfiguration
{
    string Name { get; }
}

两种类型,Person和IConfifigraphy(其实现在这里并不重要(都在温莎容器中注册。

问题:我怎样才能告诉温莎城堡容器它应该将 IConfiguration 的 Name 属性注入到 Person 类的构造函数中?

警告:我不想将 IConfiguration 注入 Person 类或使用类型化工厂......Person 类必须简单,并且只接受字符串作为参数。

如何构造函数注入仅在运行时已知的字符串?(温莎城堡)

由于温莎非常灵活,可能还有更多方法可以做到这一点,但这里有三种方法可以让我想到:

选项 1:

如果IConfiguration是单例,或者可以在没有任何其他帮助的情况下以某种方式填充Name,则可以执行以下操作:

container.Register(Component.For<IConfiguration>().ImplementedBy<Configuration>());
container.Register(Component
    .For<Person>()
    .DynamicParameters((DynamicParametersDelegate)ResolvePersonName));
// This should be a private method in your bootstrapper 
void ResolvePersonName(IKernel kernel, IDictionary parameters)
{
    parameters["name"] = kernel.Resolve<IConfiguration>().Name;
}

此方法在解析Person之前被调用,并将name键/值对设置为所需的值。 然后,Windsor 使用此字典重写构造函数中的任何依赖项。 我可能会把它变成一个 lambda 来更可怕:

    .DynamicParameters((k,p) => p["name"] = k.Resolve<IConfiguration>().Name));

选项 2:

如果Name值实际上是在应用程序设置文件中定义的,则 Windsor 有一个内置选项:

container.Register(
    Component.For<Person>()
    .DependsOn(Dependency.OnAppSettingsValue("name", "configSettingKeyName")));

选项 3:

你说你不想使用类型化工厂

,但我认为这是使用类型化工厂的合理选择。 它根本不会使Person类复杂化,但它会为创建Person对象(人?(的代码添加一点。 下面是一个示例:

定义工厂接口:

public interface IPersonFactory
{
    Person Create(string name);
}

然后在创建Person的位置,注入工厂并改用它:

public class PersonUser
{
    public Personuser(IConfiguration configuration, IPersonFactory personFactory)
    {
        Person person = personFactory.Create(configuration.Name);
    }
}

您必须添加工具并注册接口,但这很容易:

container.AddFacility<TypedFactoryFacility>();
container.Register(Component.For<IPersonFactory>().AsFactory());