Заменить регистрацию в Autofac - PullRequest
6 голосов
/ 15 февраля 2011

У меня есть приложение, которое выполняет обработку данных.Существует

class Pipeline {
  IEnumerable<IFilter> Filters {get; set;}

Я регистрирую реализации фильтров как

builder.RegisterType<DiversityFilter>().As<IFilter>();
builder.RegisterType<OverflowFilter>().As<IFilter>();
...

Пока все хорошо.Теперь для экспериментов и тонкой настройки я хочу иметь возможность переопределить любую реализацию фильтра в конфигурационном файле с помощью программы (сценария), которая будет считывать данные из stdin, обрабатывать их и отправлять данные в stdout.Я реализовал модуль с пользовательскими свойствами «fileName», «args» и «replaceOf», описал модуль в XML и получил его.

В модуле я регистрирую свой «ExecutableFilter», но как мне сделатьэто запустить "вместо" желаемого сервиса?Если я попытаюсь сделать это следующим образом:

builder.RegisterType<ExecutableFilter>().As<DiversityFilter>()

, тогда я получу исключение «Тип ExecutableFilter не может быть назначен службе« DiversityFilter ».».Хорошо, это логично.Но каковы мои варианты тогда?

Ответы [ 2 ]

9 голосов
/ 16 февраля 2011

После того, как вы отменили регистрацию для IFilter «После» с помощью своего касания, вы не сможете разрешить его из контейнера, так как вместо этого будет активирована новая регистрация, отсюда и круговой поиск.

Вместо этого создайте и зарегистрируйте модуль, который подключится к созданию фильтра и заменит экземпляр на «подключенный к проводу»:

class WiretapModule : Module
{
  override void AttachToComponentRegistration(
           IComponentRegistration registration,
           IComponentRegistry registry)
  {
    if (registration.Services.OfType<KeyedService>().Any(
          s => s.ServiceKey == After && s.ServiceType == typeof(IFilter))) 
    {
      registration.Activating += (s, e) => {
        e.Instance = new WireTap((IFilter)e.Instance, new ExecuteProvider(fileName, args))
      };
    }
  }
}

(Перекрестная публикация в группе Autofac: https://groups.google.com/forum/#!topic/autofac/yLbTeuCObrU)

2 голосов
/ 15 февраля 2011

То, что вы описываете, является частью работы контейнера, частью бизнес-логики.Задача состоит в том, чтобы сохранить разделение проблем здесь.ИМО, контейнер должен делать то, что он должен делать, то есть создавать и обслуживать экземпляры или их коллекции.Не следует делать «вместо» в этом случае.Я бы предпочел «обогатить» сервисы достаточным количеством информации, чтобы конвейер принял решение.

«Обогащение» можно выполнить, заставив ExecutableFilter реализовать более четкий интерфейс.

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

...