是否可以在 Unity 或其他类型的IoC库中注入依赖项列表?
public class Crawler
{
public Crawler(IEnumerable<IParser> parsers)
{
// init here...
}
}
通过这种方式,我可以在我的容器中注册多个IParser,然后解决它们。
有可能吗?感谢
答案 0 :(得分:9)
这是可能的,但您需要应用一些解决方法。首先,您需要在Unity容器中使用名称注册每个 IParser 。其次,您需要在容器中注册从 IParser [] 到 IEnumerable&lt; IParser&gt; 的映射。否则,容器无法将解析器注入构造函数。以下是我以前的做法。
IUnityContainer container = new UnityContainer();
container.RegisterType<IParser, SuperParser>("SuperParser");
container.RegisterType<IParser, DefaultParser>("DefaultParser");
container.RegisterType<IParser, BasicParser>("BasicParser");
container.RegisterType<IEnumerable<IParser>, IParser[]>();
container.RegisterType<Crawler>();
Crawler crawler = container.Resolve<Crawler>();
我放弃了这个解决方案,引入了一个工厂,它封装了统一来构建所需的类型。以下是我将如何处理你的情况。
public interface IParserFactory{
IEnumerable<IParser> BuildParsers();
}
public class UnityParserFactory : IParserFactory {
private IUnityContainer _container;
public UnityParserFactory(IUnityContainer container){
_container = container;
}
public IEnumerable<IParser> BuildParsers() {
return _container.ResolveAll<IParser>();
}
}
public class Crawler {
public Crawler(IParserFactory parserFactory) {
// init here...
}
}
使用此功能,您可以按如下方式注册类型:
IUnityContainer container = new UnityContainer();
container.RegisterType<IParser, SuperParser>();
container.RegisterType<IParser, DefaultParser>();
container.RegisterType<IParser, BasicParser>();
container.RegisterType<IParserFactory, UnityParserFactory>();
Crawler crawler = container.Resolve<Crawler>();
答案 1 :(得分:0)
不是说我说这是错的,但似乎你正在尝试解决一个插件模型,你可以通过使用MEF来轻松管理。提示将被继承从界面导出,然后在需要解析器时执行ImportMany。
答案 2 :(得分:0)
事实上,我不知道不支持这个的任何容器。
但是,作为一般性建议,如果可以,可以通过将该列表包装在composite中,并将该组合注入消费者,来防止将服务列表注入消费者。不将列表包装在复合中会使应用程序混乱使用额外的foreach
循环,或者您需要做什么来处理该依赖项列表。虽然这似乎并不坏,但这些依赖关系的消费者不应该关心。但更糟糕的是,当我们想要改变处理服务列表的方式时,我们将不得不通过完整的应用程序,这违反了DRY原则。
当消费者(在您的情况下为Crawler
)属于Composition Root而不是应用程序本身时,此建议不成立。此外,当应用程序只有一个消费者接受这种依赖时,它可能没那么大。
答案 3 :(得分:0)
有很多方法可以在Unity中实现这一目标。例如,
http://sharpsnmplib.codeplex.com/SourceControl/changeset/view/5497af31d15e#snmpd%2fapp.config
<register type="UserRegistry">
<lifetime type="singleton" />
<constructor>
<param name="users" dependencyType="User[]" />
</constructor>
</register>
此构造函数需要一个User对象数组,并且在创建UserRegistry对象时,Unity会将此容器中定义的所有此类对象注入其中。
答案 4 :(得分:-1)