Введение данных к сервису WCF

У меня есть сервисы WCF, структурированные как предложенный Miguel Castro. Это означает, что я настроил все вручную и имею консольное приложение, размещающее мое сервисное использование объекты ServiceHost.

Я хочу сохранить свои классы обслуживания тонкими, и они в настоящее время просто передают вызовы классам поведения. Моей проблемой теперь является поблочное тестирование классы обслуживания. Я хочу ввести что-то к классам как параметр конструктора, таким образом, что я могу дразнить это далеко и записать надлежащие изолированные модульные тесты. Класс ServiceHost, кажется, не принимает аргументы, таким образом, мой вопрос состоит в том, как я могу ввести данные к классам обслуживания - или не могу я?

20
задан stiank81 11 January 2010 в 22:41
поделиться

3 ответа

Кажется, этот пост имеет ответ: в основном, вы должны начать не с клона, а инициализировать и извлечь. Сам не пробовал (пока)...

-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 Бедного человека.

32
ответ дан 30 November 2019 в 00:01
поделиться

Если бы вы использовали Castle Windsor, у него есть отличный объект интеграции WCF, который позволяет вам сделать это, и намного более легко.

5
ответ дан 30 November 2019 в 00:01
поделиться

Вы настроили свой сервис как синглтон? Я обнаружил, что реализации IinstanceProvider могут быть проблематичными при использовании дистанции DI для создания экземпляров обслуживания.

1
ответ дан 30 November 2019 в 00:01
поделиться
Другие вопросы по тегам:

Похожие вопросы: