首页 文章

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

提问于
浏览
1

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

我做了以下事情:

Custom ServiceHost

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

Custom Instance Provider

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

但是我没有进入 GetInstance ,当我运行代码时,我得到了这个:

提供的服务类型无法作为服务加载,因为它没有默认(无参数)构造函数 . 要解决此问题,请为该类型添加默认构造函数,或将该类型的实例传递给主机 .

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

1 回答

  • 1

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

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

    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上,我无法创建这种行为

相关问题