简体   繁体   English

Unity .NET:依赖项列表

[英]Unity .NET: List of dependencies

Is it possible to inject a list of dependencies like this in Unity or other kind of IoC libraries? 是否可以在Unity或其他类型的IoC库中注入这样的依赖项列表

public class Crawler 
{
    public Crawler(IEnumerable<IParser> parsers) 
    {
         // init here...
    }
}

In this way I can register multiple IParser in my container and then resolve them. 通过这种方式,我可以在我的容器中注册多个IParser,然后解决它们。

Is it possible? 可能吗? Thanks 谢谢

It is possible but you need to apply some workarounds. 这是可能的,但您需要应用一些变通方法。 First you need to register each IParser with a name in the Unity Container. 首先,您需要在Unity容器中使用名称注册每个IParser Second you need to register a mapping from IParser[] to IEnumerable<IParser> in the container. 其次,您需要在容器中注册从IParser []IEnumerable <IParser>的映射。 Otherwise the container cannot inject the parsers to the constructor. 否则,容器无法将解析器注入构造函数。 Here´s how i have done it before. 以下是我以前的做法。

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>();

I have discarded this solution by introducing a factory, that encapsulates unity to construct the needed types. 我通过引入一个工厂来废弃这个解决方案,这个工厂封装了统一来构建所需的类型。 Here´s how i would do it in your case. 以下是我将如何处理你的情况。

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...
  }
}

With this you can register the types as follows: 有了这个,你可以注册类型如下:

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>();

Not that I'm saying it's wrong but it seems like you are trying to solve a plugin model that you could easily manage with the use of MEF instead. 并不是说我说这是错的,但似乎你正在尝试解决一个插件模型,你可以通过使用MEF来轻松管理。 Hints would be inherited Export from the interface and then do ImportMany when you need the parsers. 提示将被继承从界面导出,然后在需要解析器时执行ImportMany。

As a matter of fact, I don't know any container that does not support this. 事实上,我不知道任何支持这个的容器。

However, as a general advice, you should prevent injecting lists of services into consumers if you can, by wrapping that list in a composite , and inject that composite into consumers. 但是,作为一般建议,如果可以,可以通过将该列表包装在组合中 ,并将该组合注入到使用者中来防止将服务列表注入到使用者中。 Not wrapping the list in a composite would clutter the application with extra foreach loops or what ever you need to do to process that list of dependencies. 不将列表包装在复合中会使应用程序混乱使用额外的foreach循环,或者您需要做什么来处理该依赖项列表。 While this doesn't seem bad, the consumers of these dependencies shouldn't care. 虽然这似乎并不坏,但这些依赖关系的消费者不应该关心。 But worse, when we want to change the way the list of services is handled, we will have to go through the complete application, which is a violation of the DRY principle. 但更糟糕的是,当我们想要改变处理服务列表的方式时,我们将不得不通过完整的应用程序,这违反了DRY原则。

This advice does not hold when the consumer (in your case the Crawler ) is part of the Composition Root instead of the application itself. 当消费者(在您的情况下是Crawler )是Composition Root的一部分而不是应用程序本身时,此建议不成立。 Further more, when the application only has a single consumer that takes this dependency, it might not be that big of deal. 此外,当应用程序只有一个消费者接受这种依赖时,它可能不是那么大的交易。

There are ways to achieve this in Unity. 有很多方法可以在Unity中实现这一目标。 For example, 例如,

http://sharpsnmplib.codeplex.com/SourceControl/changeset/view/5497af31d15e#snmpd%2fapp.config 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>

This constructor requires an array of User objects, and all such objects defined in this container are injected by Unity into it when the UserRegistry object is created. 此构造函数需要一个User对象数组,并且在创建UserRegistry对象时,Unity会将此容器中定义的所有此类对象注入其中。

yes you can.. you can look at dependency injectors. 是的,你可以..你可以看看依赖注射器。 I am a big fan of the Autofac project. 我是Autofac项目的忠实粉丝。

Another option is Ninject , 另一种选择是Ninject

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM