如何在WCF服务中注入依赖项

时间:2017-07-26 12:00:03

标签: c# wcf dependency-injection

我正在尝试在WCF服务中注入一些业务服务。我读了这篇非常有意思的帖子:How do I pass values to the constructor on my wcf service?

我做了以下事情:

自定义ServiceHost

autocmd WinEnter,BufWinEnter,FileType,ColorScheme,SessionLoadPost * let w:left = StatuslineComponents('left')
let &statusline = "%{w:left}%=%{StatuslineComponents('right')}"

自定义实例提供程序

    public class UnityServiceHost : ServiceHost
    {
        public UnityServiceHost(IUnityContainer container, Type serviceType, params Uri[] baseAddresses)
            : base(serviceType, baseAddresses)
        {
            if (container == null)
            {
                throw new ArgumentNullException(nameof(container));
            }

            foreach (ContractDescription contractDescription in ImplementedContracts.Values)
            {
                contractDescription.Behaviors.Add(new UnityInstanceProvider(serviceType, container));
            }
        }
    }

我看起来像这样的服务行为:

public class UnityInstanceProvider : IInstanceProvider, IContractBehavior
{
    private readonly Type m_serviceType;
    private readonly IUnityContainer m_container;

    public UnityInstanceProvider(Type serviceType, IUnityContainer container)
    {
        m_serviceType = serviceType;
        m_container = container;
    }
    public object GetInstance(InstanceContext instanceContext, Message message)
    {
        return GetInstance(instanceContext);
    }
    public object GetInstance(InstanceContext instanceContext)
    {
        return m_container.Resolve(m_serviceType);
    }
    public void ReleaseInstance(InstanceContext instanceContext, object instance)
    {
        (instance as IDisposable)?.Dispose();
    }
    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)     {       }
}

但是我没有进入[ServiceBehavior] public class MyService : IMyService { public ServerInformationService(ISomeDependency coreManager) { //... } } ,当我运行代码时,我得到了这个:

  

提供的服务类型无法作为服务加载,因为它   没有默认(无参数)构造函数。修复   问题,向类型添加默认构造函数,或传递实例   主机的类型。

我做错了什么?看起来我的实例提供程序甚至没有使用

1 个答案:

答案 0 :(得分:1)

我终于找到了解决方案。我将我的InstanceProvider应用于联系而不是服务。

这是我的最终(工作)解决方案:

public class UnityServiceHost : ServiceHost
{
    public UnityServiceHost(IUnityContainer container, Type serviceType, params Uri[] baseAddresses)
        : base(serviceType, baseAddresses)
    {
        if (container == null)
        {
            throw new ArgumentNullException(nameof(container));
        }
        Description.Behaviors.Add(new UnityInstanceProvider(serviceType, container));
    }
}

行为+实例提供者:

public class UnityInstanceProvider : IInstanceProvider, IServiceBehavior
{
    private readonly Type m_serviceType;
    private readonly IUnityContainer m_container;

    public UnityInstanceProvider(Type serviceType, IUnityContainer container)
    {
        m_serviceType = serviceType;
        m_container = container;
    }

    public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {
    }

    public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
    {
    }

    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {
        foreach (ChannelDispatcherBase channelDispatcherBase in serviceHostBase.ChannelDispatchers)
        {
            ChannelDispatcher cd = (ChannelDispatcher)channelDispatcherBase;
            foreach (EndpointDispatcher ed in cd.Endpoints)
            {
                if (!ed.IsSystemEndpoint)
                {
                    ed.DispatchRuntime.InstanceProvider = this;
                }
            }
        }
    }

    public object GetInstance(InstanceContext instanceContext)
    {
        return m_container.Resolve(m_serviceType);
    }

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

    public void ReleaseInstance(InstanceContext instanceContext, object instance)
    {
        (instance as IDisposable)?.Dispose();
    }
}

它的工作原理是因为我是自托管服务(new UnityServiceHost(...) ....,如果它在IIS上,我无法以这种方式创建行为