Настройка Ninject для WCF

Есть ли у кого четкая инструкция по настройке Ninject в WCF? был googling, но я не вижу никаких обновленных рекомендаций о том, как использовать Ninject в WCF.

Ответ 1

Использование NInject с WCF аналогично использованию любого другого контейнера DI. Для этого вам необходимо использовать 3 точки расширяемости WCF: InstanceProvider, ServiceHost и ServiceHostFactory.

Пользовательский InstanceProvider будет использоваться для создания экземпляров службы с помощью конструктора с параметрами. Код можно увидеть ниже.

public class NInjectInstanceProvider : IInstanceProvider, IContractBehavior
{
    private readonly IKernel kernel;

    public NInjectInstanceProvider(IKernel kernel)
    {
        if (kernel == null) throw new ArgumentNullException("kernel");
        this.kernel = kernel;
    }

    public object GetInstance(InstanceContext instanceContext, Message message)
    {
        //delegate to GetInstance(InstanceContext)
        return GetInstance(instanceContext);
    }

    public object GetInstance(InstanceContext instanceContext)
    {
        //resolve the service instance
        return kernel.Get(instanceContext.Host.Description.ServiceType);
    }

    public void ReleaseInstance(InstanceContext instanceContext, object instance)
    {
        kernel.Release(instance);
    }

    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)
    {
    }
}

Этот пользовательский поставщик экземпляра затем применяется к каждому контракту в классе ServiceHost. Это делается с использованием поведения контракта. Вот почему поставщик экземпляра также реализует IContractBehavior. Вы можете видеть, что мы применяем поставщика экземпляра в методе ApplyDispatchBehavior. В приведенном ниже коде представлены реализации ServiceHost и ServiceHostFactory.

public class NInjectServiceHostFactory : ServiceHostFactory
{
    private readonly IKernel kernel;

    public NInjectServiceHostFactory()
    {
        kernel = new StandardKernel();
        kernel.Bind<IDummyDependency>().To<DummyDepencency>();
        //add the rest of the mappings here
    }

    protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
    {
        return new NInjectServiceHost(kernel, serviceType, baseAddresses);
    }
}

public class NInjectServiceHost : ServiceHost
{
    public NInjectServiceHost(IKernel kernel, Type serviceType, params Uri[] baseAddresses)
        : base(serviceType, baseAddresses)
    {
        if (kernel == null) throw new ArgumentNullException("kernel");
        foreach (var cd in ImplementedContracts.Values)
        {
            cd.Behaviors.Add(new NInjectInstanceProvider(kernel));
        }
    }
}

Вы можете видеть, что внутри конструктора ServiceHost мы перебираем все реализованные контракты и применяем требуемое поведение. В нашем случае это NInjectInstanceProvider.

Пользовательский ServiceHostFactory требуется для создания контейнера DI и заполнения его сопоставлениями. Затем мы переопределяем метод CreateServiceHost, чтобы предоставить нашу пользовательскую реализацию ServiceHost.

Настройка завершена в этот момент. Все, что вам нужно сделать, это создать службу WCF, которая имеет зависимость от IDummyDependency. Кроме того, не забудьте установить атрибут Factory в файле svc, как показано ниже (щелкните правой кнопкой мыши на файле svc, затем "View Markup" ):

<%@ ServiceHost Language="C#" Debug="true" Service="Service.DummyService" Factory="Service.NInjectServiceHostFactory" %>

Надеюсь, это поможет. Кроме того, я думаю, что NInject предлагает некоторые реализации для этого из коробки в NInject.Extensions.Wcf.dll.