我的类依赖于string:
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和IConfiguration(其实现在这里并不重要)都在Windsor容器中注册。
问题:如何告诉WindsorCastle容器它应该将IConfiguration的Name属性注入Person类的构造函数?
警告:我不想将IConfiguration注入Person类或使用类型化工厂...... Person类必须简单并且只接受字符串作为参数。
答案 0 :(得分:5)
可能有更多的方法可以做到这一点,因为温莎是非常灵活的,但这里有三个我的头顶:
如果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));
如果在应用程序设置文件中实际定义了Name
值,Windsor有一个内置选项:
container.Register(
Component.For<Person>()
.DependsOn(Dependency.OnAppSettingsValue("name", "configSettingKeyName")));
你说你不想使用Typed Factories,但我认为这是一个合理的使用方法。它根本不会使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());