如何构造函数注入仅在运行时已知的字符串?(温莎城堡)
本文关键字:字符串 城堡 注入 构造函数 运行时 | 更新日期: 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());