Joe*_*ein 2 ioc-container autofac
我目前正在学习Autofac的API,而我正试图把我的脑袋看作是一个非常常见的用例.
我有一个类(对于这个简单的例子'MasterOfPuppets'),它有一个通过构造函数注入('NamedPuppet')接收的依赖,这个依赖需要一个用(string name)构建的值:
public class MasterOfPuppets : IMasterOfPuppets
{
IPuppet _puppet;
public MasterOfPuppets(IPuppet puppet)
{
_puppet = puppet;
}
}
public class NamedPuppet : IPuppet
{
string _name;
public NamedPuppet(string name)
{
_name = name;
}
}Run Code Online (Sandbox Code Playgroud)
我用它们的接口注册这两个类,而不是我想要解析IMasterOfPuppets,并将一个字符串注入到'NamedPuppet'的实例中.
我尝试以下列方式执行此操作:
IMasterOfPuppets master = bs.container.Resolve<IMasterOfPuppets>(new NamedParameter("name", "boby"));Run Code Online (Sandbox Code Playgroud)
这以运行时错误结束,所以我猜Autofac只会尝试将其注入'MasterOfPuppets'.
所以我的问题是,我怎样才能解决'IMasterOfPuppets'并以最优雅的方式将参数参数传递给它的依赖?其他ioc容器有更好的解决方案吗?
Autofac不支持将参数传递给父/消费者对象,并将这些参数细化为子对象.
一般来说,我要求消费者要知道其依赖关系的界面背后是什么是糟糕的设计.让我解释:
从您的设计中,您有两个接口:IMasterOfPuppets和IPuppet.在示例中,您只有一种类型IPuppet- NamedPuppet.请记住,即使拥有接口是将接口与实现分开,您可能还会在系统中使用此接口:
public class ConfigurablePuppet : IPuppet
{
private string _name;
public ConfigurablePuppet(string name)
{
this._name = ConfigurationManager.AppSettings[name];
}
}
Run Code Online (Sandbox Code Playgroud)
有两点需要注意.
首先,当与消费者一起使用时,您应该使用不同的实现来IPuppet代替任何其他实现.在实施永远不应该知道的实施改变了... ...和消费的东西应该是进一步去除.IPuppetIMasterOfPuppetsIMasterOfPuppetsIPuppetIMasterOfPuppets
其次,示例NamedPuppet和new都ConfigurablePuppet采用具有相同名称的字符串参数,但这意味着与支持实现不同.因此,如果您的消费代码正在执行您在示例中显示的内容 - 传入一个旨在作为事物名称的参数- 那么您可能遇到了界面设计问题.见:利斯科夫替代原则.
点是,考虑到IMasterOfPuppets 执行需要一个IPuppet传入,它不应该关心如何将IPuppet其构建为开始或什么是真正来头IPuppet.一旦它知道,你就会打破界面和实现的分离,这意味着你可以不再使用界面而只是一直传入NamedPuppet对象.
就传递参数而言,Autofac确实有参数支持.
推荐和最常见的参数传递类型是在注册期间,因为那时您可以在容器级别设置并且您没有使用服务位置(通常被认为是反模式).
如果您需要在分辨率期间传递参数,Autofac也支持该功能.然而,当在解决期间通过时,它更多的是服务定位器并且不是那么大,因为它再次暗示消费者知道它正在消耗什么.
如果要将参数连接到来自已知源(如配置)的连接,则可以使用lambda表达式注册执行一些奇特的操作.
builder.Register(c => {
var name = ConfigurationManager.AppSettings["name"];
return new NamedPuppet(name);
}).As<IPuppet>();
Run Code Online (Sandbox Code Playgroud)
您还可以使用消费者中的Func<T>隐式关系来做一些奇特的事情:
public class MasterOfPuppets : IMasterOfPuppets
{
IPuppet _puppet;
public MasterOfPuppets(Func<string, IPuppet> puppetFactory)
{
_puppet = puppetFactory("name");
}
}
Run Code Online (Sandbox Code Playgroud)
这样做相当于在分辨率期间使用TypedParameter类型string.但是,正如你所看到的那样,它来自直接消费者,IPuppet而不是通过所有决议的堆栈渗透的东西.
最后,您还可以使用Autofac模块以log4net集成模块示例中的方式执行一些有趣的交叉操作.使用这样的技术允许您通过所有分辨率全局插入特定参数,但它不一定提供在运行时传递参数的能力 - 您必须将参数的源放在模块中.
要点是Autofac支持参数,而不是你想要做的事情.我强烈建议你重新设计你做事的方式,这样你就不需要做你正在做的事情,或者你可以用上面提到的方法解决它.
希望这能让你朝着正确的方向前进.
| 归档时间: |
|
| 查看次数: |
1366 次 |
| 最近记录: |