Unity .NET: список зависимостей - PullRequest
8 голосов
/ 20 сентября 2011

Можно ли внедрить список зависимостей , как это в Unity или других видах библиотек IoC?

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

Таким образом, я могу зарегистрировать несколько IParser в моем контейнере, а затем разрешить их.

Возможно ли это? Спасибо

Ответы [ 5 ]

10 голосов
/ 20 сентября 2011

Возможно, но вам нужно применить некоторые обходные пути. Сначала вам нужно зарегистрировать каждого IParser с именем в контейнере Unity. Во-вторых, вам нужно зарегистрировать сопоставление от 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 голосов
/ 20 сентября 2011

Есть способы достичь этого в 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, и все такие объекты, определенные в этом контейнере, внедряются Unity в него при создании объекта UserRegistry.

0 голосов
/ 20 сентября 2011

На самом деле, я не знаю ни одного контейнера, который бы не поддерживал это.

Однако, как общий совет, вы должны по возможности запретить внедрение списков услуг в потребителей, завернув этот список в составной , и внедрить этот состав в потребителей. Если вы не оберните список в составной, это приведет к загромождению приложения дополнительными foreach циклами или тем, что вам когда-либо понадобится для обработки этого списка зависимостей. В то время как это не кажется плохим, потребители этих зависимостей не должны заботиться. Но что еще хуже, когда мы хотим изменить способ обработки списка услуг, нам придется пройти через полное приложение, что является нарушением принципа DRY .

Этот совет не действует, когда потребитель (в вашем случае Crawler) является частью Composition Root вместо самого приложения. Более того, когда приложение имеет только одного потребителя, который принимает эту зависимость, это может быть не так уж сложно.

0 голосов
/ 20 сентября 2011

да, вы можете .. вы можете посмотреть на инжекторы зависимости. Я большой поклонник проекта Autofac .

Другой вариант: Ninject ,

0 голосов
/ 20 сентября 2011

Не то чтобы я говорил, что это неправильно, но похоже, что вы пытаетесь решить модель плагина, которой вы могли бы легко управлять с помощью MEF.Подсказки будут наследоваться Export из интерфейса, а затем выполнять ImportMany, когда вам нужны парсеры.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...