【问题标题】:How to inject dependencies in a WCF Service如何在 WCF 服务中注入依赖项
【发布时间】:2023-03-04 08:32:01
【问题描述】:

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

我做了以下事情:

自定义服务主机

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

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

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

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

【问题讨论】:

  • 这表明你试图注入的依赖应该有一个无参数的构造函数。
  • @ArunGeorge 我不这么认为,它不会在return m_container.Resolve(m_serviceType); 断点处停止,我可以使用 WPF 之外的依赖项请求相同的服务。跨度>
  • 您的服务是否托管在 IIS 中?你在使用UnityServiceHost 类吗?
  • @YacoubMassad 不,它是自托管的。我终于找到了问题。当我应该使用 ServiceBehavior 时,我使用了 ContractBehavior。我确认一切正常,我将发布答案

标签: c# wcf dependency-injection


【解决方案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 上,我无法以这种方式创建行为

【讨论】:

    猜你喜欢
    • 2011-09-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-26
    • 2017-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多