Unity .NET:依赖项列表

问题描述 投票:0回答:5

是否可以像这样在Unity或其他类型的IoC库中注入依赖项列表

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

通过这种方式,我可以在我的容器中注册多个IParser,然后解析它们。

可能吗?谢谢

c# dependency-injection unity-container ioc-container
5个回答
10
投票

这是可能的,但您需要应用一些解决方法。首先,您需要在 Unity 容器中使用名称注册每个IParser。其次,您需要在容器中注册从 IParser[]IEnumerable 的映射。否则容器无法将解析器注入到构造函数中。这就是我之前的做法。

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

0
投票

我并不是说这是错误的,但您似乎正在尝试解决一个可以使用 MEF 轻松管理的插件模型。提示将从接口继承 Export,然后在需要解析器时执行 ImportMany。


0
投票

事实上,我不知道有哪个容器支持这一点。

但是,作为一般建议,如果可以的话,您应该通过将该列表包装在composite中来防止将服务列表注入到消费者中,并将该组合注入到消费者中。不将列表包装在复合材料中会使应用程序因额外的

foreach
循环或处理该依赖项列表所需执行的操作而变得混乱。虽然这看起来不错,但这些依赖项的使用者不应该关心。但更糟糕的是,当我们想要更改服务列表的处理方式时,我们将必须完成完整的应用程序,这违反了DRY原则。

当消费者(在您的情况下为

Crawler
)是 Composition Root 而不是应用程序本身的一部分时,此建议不成立。此外,当应用程序只有一个消费者接受这种依赖性时,这可能没什么大不了的。


0
投票

Unity 有多种方法可以实现这一点。例如,

    <register type="UserRegistry">
      <lifetime type="singleton" />
      <constructor>
        <param name="users" dependencyType="User[]" />
      </constructor>
    </register>

这个构造函数需要一个 User 对象数组,并且在创建 UserRegistry 对象时,Unity 会将在此容器中定义的所有此类对象注入到其中。


-1
投票

是的,你可以..你可以看看依赖注入器。我是 Autofac 项目的忠实粉丝。

另一个选项是Ninject

© www.soinside.com 2019 - 2024. All rights reserved.