.net - 将数据注入(inject) WCF 服务

标签 .net wcf unit-testing dependency-injection service

我有 Miguel Castro 建议的 WCF 服务结构.这意味着我已经手动设置了所有内容,并且有一个控制台应用程序使用 ServiceHost 托管我的服务。对象。

我想让我的服务类保持精简,它们目前只是将调用传递给行为类。我现在的问题是对服务类进行单元测试。我想将一些东西作为构造函数参数注入(inject)到类中,这样我就可以模拟它并编写适当的隔离单元测试。 ServiceHost 类似乎不接受参数,所以我的问题是如何将数据注入(inject)服务类 - 还是不能?

最佳答案

WCF 支持 构造函数注入(inject) ,但你必须跳过几个圈才能到达那里。关键在于编写一个自定义的 ServiceHostFactory。虽然它也必须有一个默认构造函数,但您可以使用它来连接所有正确的行为。

举个例子,我最近写了一个使用 CaSTLe Windsor 来连接服务实现的依赖项。 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));
        }
    }
}

WindsorInstanceProvider 看起来像这样:
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 容器或使用 Poor Man 的 DI 来实现依赖注入(inject)。

这是 older writeup使用Poor Man's DI的这个成语。

关于.net - 将数据注入(inject) WCF 服务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2042609/

相关文章:

.net - 如何确保从 mysql 数据库中提取的数据在 Mssql 和 SSIS 中被识别?

c# - 在其他所有内容后面显示一个表单,而不窃取焦点?

c# - dotnet 返回 2 种类型中的 1 种

c# - WCF 用户名密码验证器缓存

对注入(inject)了另一个 ejb 的 ejb3.0 进行单元测试

c# - 测试结果中未复制所有程序集 - MS 测试

wcf - 使用 new-webproxyservice 从 powershell 调用 wcf 的奇怪行为

c# - WCF 服务应该返回普通的旧对象,还是您正在使用的实际类?

c# - NUnit 是否支持 C# 动态的流畅语法?

unit-testing - 我可以将类型参数传递给 DUnitx 中的测试用例吗?