Как зарегистрировать два контракта на обслуживание WCF с autofac

У меня есть служба WCF, которая реализует два контракта на обслуживание...

public class MyService : IService1, IService2

и я сам предоставляю услуги...

host = new ServiceHost(typeof(MyService));

Все работало нормально, когда служба реализовала только один контракт на обслуживание, но когда я пытаюсь настроить autofac для регистрации так:

host.AddDependencyInjectionBehavior<IService1>(_container);
host.AddDependencyInjectionBehavior<IService2>(_container);

... он выдает исключение на втором, сообщая:

Значение не может быть добавлено в коллекцию, так как коллекция уже содержит элемент того же типа: "Autofac.Integration.Wcf.AutofacDependencyInjectionServiceBehavior". Эта коллекция поддерживает только один экземпляр каждого типа.

На первый взгляд, я думал, что это говорит о том, что мои два контракта были как-то похожими на то же, но во втором чтении я считаю, что это говорит о том, что AutofacDependencyInjectionServiceBehavior - это тип, о котором идет речь, т.е. Я не могу использовать его дважды!

И все же я нашел этот пост, который явно показывал его несколько раз в несколько иной форме:

foreach (var endpoint in host.Description.Endpoints)
{
  var contract = endpoint.Contract;
  Type t = contract.ContractType;
  host.AddDependencyInjectionBehavior(t, container);
}

К сожалению, это дало такое же сообщение об ошибке.

Возможно ли зарегистрировать более одного контракта на одну услугу, и если да, то как?

Ответ 1

Фактически вы можете зарегистрировать несколько конечных точек для одного хоста с помощью Autofac.

Верно, что вы не можете добавить несколько AutofacDependencyInjectionServiceBehavior, но это поведение повторяется через все конечные точки и регистрирует их в методе ApplyDispatchBehavior: source

Для выполнения этой работы вам необходимо зарегистрировать свою службу AsSelf()

builder.RegisterType<MyService>();

Затем вы можете настроить конечную точку как обычно:

host = new ServiceHost(typeof(MyService));
host.AddServiceEndpoint(typeof(IService1), binding, string.Empty);
host.AddServiceEndpoint(typeof(IService2), binding, string.Empty);

И, наконец, вам нужно вызвать AddDependencyInjectionBehavior с самим типом sevicehost:

host.AddDependencyInjectionBehavior<MyService>(container);

Вот небольшой образец проекта (на основе документации), который демонстрирует это поведение.

Ответ 2

Обновить (полужирный текст) на основе ответа @nemesv:

Дальнейшее исследование показало, что при автофаке нельзя регистрировать несколько конечных точек на одном ServiceHost , если регистрировать контракты на обслуживание WCF. (См. @nemesv ответ за правильный способ сделать это.)

Вот почему:

Любая форма этого метода расширения...

host.AddDependencyInjectionBehavior<IService1>(_container);
host.AddDependencyInjectionBehavior(t, container);

... решает до добавления ServiceBehavior (согласно Alex Meyer-Gleaves начальное объявление интеграции WCF в autofac)...

host.Description.Behaviors.Add(behavior);

Теперь это свойство Behaviors является экземпляром KeyedByTypeCollection <TItem> ;, который может содержать только один объект определенного типа. Поскольку добавляемое поведение всегда будет экземпляром AutofacDependencyInjectionServiceBehavior, можно поэтому добавить только одну конечную точку.

КЭД

Обходной путь заключается в использовании нескольких ServiceHosts, каждый с одной конечной точкой.

(Как интересно, мне было бы интересно узнать о влиянии на производительность и масштабируемость между этими двумя подходами.)