У меня есть сервисы WCF, структурированные как предложенный Miguel Castro. Это означает, что я настроил все вручную и имею консольное приложение, размещающее мое сервисное использование объекты ServiceHost.
Я хочу сохранить свои классы обслуживания тонкими, и они в настоящее время просто передают вызовы классам поведения. Моей проблемой теперь является поблочное тестирование классы обслуживания. Я хочу ввести что-то к классам как параметр конструктора, таким образом, что я могу дразнить это далеко и записать надлежащие изолированные модульные тесты. Класс ServiceHost, кажется, не принимает аргументы, таким образом, мой вопрос состоит в том, как я могу ввести данные к классам обслуживания - или не могу я?
Кажется, этот пост имеет ответ: в основном, вы должны начать не с клона, а инициализировать и извлечь. Сам не пробовал (пока)...
-121--2991239-Вы не можете обойти это ограничение напрямую, нет. Но в вашем конкретном случае вы можете сделать что - то разумное.
Например, можно просто «создать» экземпляр класса в статическом методе, а затем вызвать нестатический метод.
Но вы можете получить еще лучшие предложения, если опубликуете свой класс (ы) - или их худшую версию.
-121--691426-WCF поддерживает Впрыск конструктора , но вам нужно пройти через несколько обручей, чтобы попасть туда. Ключ заключается в написании настраиваемого ServiceHostFactory. Хотя у этого конструктора также должен быть конструктор по умолчанию, его можно использовать для подключения всех правильных вариантов поведения.
В качестве примера я недавно написал один, который использует замок Виндзор для согласования зависимостей для реализации услуги. Реализация CreateServiceHost выполняется следующим образом:
return new WindsorServiceHost(this.container, serviceType, baseAddresses);
, где this.container
является настроенным IWindsorContainer.
WindsorServiceHost выглядит следующим образом:
public class WindsorServiceHost : ServiceHost
{
public WindsorServiceHost(IWindsorContainer container, Type serviceType, params Uri[] baseAddresses)
: base(serviceType, baseAddresses)
{
if (container == null)
{
throw new ArgumentNullException("container");
}
foreach (var cd in this.ImplementedContracts.Values)
{
cd.Behaviors.Add(new WindsorInstanceProvider(container));
}
}
}
, а WindSorateProvider выглядит следующим образом:
public class WindsorInstanceProvider : IInstanceProvider, IContractBehavior
{
private readonly IWindsorContainer container;
public WindsorInstanceProvider(IWindsorContainer container)
{
if (container == null)
{
throw new ArgumentNullException("container");
}
this.container = container;
}
#region IInstanceProvider Members
public object GetInstance(InstanceContext instanceContext, Message message)
{
return this.GetInstance(instanceContext);
}
public object GetInstance(InstanceContext instanceContext)
{
var serviceType = instanceContext.Host.Description.ServiceType;
return this.container.Resolve(serviceType);
}
public void ReleaseInstance(InstanceContext instanceContext, object instance)
{
this.container.Release(instance);
}
#endregion
#region IContractBehavior Members
public void AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
}
public void ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
}
public void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime)
{
dispatchRuntime.InstanceProvider = this;
}
public void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint)
{
}
#endregion
}
Это может выглядеть как много, но обратите внимание, что это многоразовый код общего назначения, который имеет довольно низкую цикломатическую сложность.
Вы можете следовать той же самой идиоме кодирования, чтобы реализовать инъекцию зависимостей с другим контейнером DI или используя DI бедного человека.
Вот старая запись этой идиомы, которая использует DI Бедного человека.
Если бы вы использовали Castle Windsor, у него есть отличный объект интеграции WCF, который позволяет вам сделать это, и намного более легко.
Вы настроили свой сервис как синглтон? Я обнаружил, что реализации IinstanceProvider могут быть проблематичными при использовании дистанции DI для создания экземпляров обслуживания.