Как зарегистрировать два контракта на обслуживание 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, каждый с одной конечной точкой.
(Как интересно, мне было бы интересно узнать о влиянии на производительность и масштабируемость между этими двумя подходами.)