[英]How to constructor-inject a string that is only known at runtime? (Windsor Castle)
I have class that has dependency on string: 我有一个依赖于字符串的类:
public class Person
{
private readonly string _name;
public Person(string name)
{
if (name == null) throw new ArgumentNullException("name");
_name = name;
}
}
This string 'name' is known only at runtime, eg. 该字符串'name'仅在运行时才知道,例如。 it is defined in configuration. 它在配置中定义。 So I have this interface that provides this string: 所以我有这个提供这个字符串的接口:
public interface IConfiguration
{
string Name { get; }
}
Both types, Person and IConfiguration (with its implementation which is not important here) are registered with Windsor container. 这两种类型,Person和IConfiguration(其实现在这里并不重要)都在Windsor容器中注册。
Question: how can I tell WindsorCastle container that it should inject the Name property of IConfiguration to the constructor of Person class? 问题:如何告诉WindsorCastle容器它应该将IConfiguration的Name属性注入Person类的构造函数?
Caveat: I don't want to inject IConfiguration to Person class or use typed factories... the Person class must be simple and accept only string as parameter. 警告:我不想将IConfiguration注入Person类或使用类型化的工厂...... Person类必须简单并且只接受字符串作为参数。
There are probably more ways to do this since Windsor is ridiculously flexible, but here are three off the top of my head: 可能有更多的方法可以做到这一点,因为温莎是非常灵活的,但这里有三个我的头顶:
If IConfiguration
is a singleton or somehow can populate Name
without any other assistance, you could do the following: 如果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;
}
This method is invoked before resolving the Person
, and is setting the name
key/value pair to be the desired value. 在解析Person
之前调用此方法,并将name
键/值对设置为所需的值。 Windsor then uses this dictionary to override any dependencies in the constructor. 然后,Windsor使用此字典覆盖构造函数中的任何依赖项。 I'd probably just make it a lambda to be terser: 我可能只是让它成为一个lambda:
.DynamicParameters((k,p) => p["name"] = k.Resolve<IConfiguration>().Name));
If the Name
value is actually defined in the applications settings file, Windsor has a built-in option for that: 如果Name
值实际上是在应用程序设置文件中定义的,那么Windsor有一个内置选项:
container.Register(
Component.For<Person>()
.DependsOn(Dependency.OnAppSettingsValue("name", "configSettingKeyName")));
You say you don't want to use Typed Factories , but I think this is a reasonable siutation for using one. 你说你不想使用Typed Factories ,但我认为这是一个合理的使用方法。 It wouldn't complicate the Person
class at all, but it would add a bit to the code creating the Person
objects (people?). 它根本不会使Person
类复杂化,但它会为创建Person
对象的代码添加一些内容(人?)。 Here's an example: 这是一个例子:
Define the factory interface: 定义工厂界面:
public interface IPersonFactory
{
Person Create(string name);
}
Then where you are creating your Person
, inject the factory and use that instead: 然后在您创建Person
,注入工厂并使用它:
public class PersonUser
{
public Personuser(IConfiguration configuration, IPersonFactory personFactory)
{
Person person = personFactory.Create(configuration.Name);
}
}
You'll have to add the facility and register the interface, but it's easy: 您必须添加设施并注册界面,但这很容易:
container.AddFacility<TypedFactoryFacility>();
container.Register(Component.For<IPersonFactory>().AsFactory());
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.