将数据注入 WCF 服务 [英] Injecting data to a WCF service

查看:24
本文介绍了将数据注入 WCF 服务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的 WCF 服务结构类似于 Miguel Castro 所建议的结构.这意味着我已手动设置所有内容,并使用 ServiceHost 对象.

I have WCF services structured like suggested by Miguel Castro. This means that I have set everything up manually, and have a console application hosting my services using ServiceHost objects.

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

I want to keep my service classes thin, and they are currently just passing on calls to behavior classes. My problem now is unit testing the service classes. I want to inject something to the classes as a constructor parameter such that I can mock this away and write proper isolated unit tests. The ServiceHost class doesn't seem to accept arguments, so my question is how I can inject data to the service classes - or can't I?

推荐答案

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

WCF supports Constructor Injection, but you have to jump through a few hoops to get there. The key lies in writing a custom ServiceHostFactory. While that, too, must have a default constructor, you can use it to wire up all the correct behaviors.

举个例子,我最近写了一个使用 Castle Windsor 来连接服务实现的依赖项.CreateServiceHost 的实现只是这样做:

As an example, I recently wrote one that uses Castle Windsor to wire up dependencies for the service implementation. The implementation of CreateServiceHost simply does this:

return new WindsorServiceHost(this.container, serviceType, baseAddresses);

其中 this.container 是配置的 IWindsorContainer.

where this.container is a configured IWindsorContainer.

WindsorServiceHost 看起来像这样:

WindsorServiceHost looks like this:

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 看起来像这样:

and WindsorInstanceProvider looks like this:

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
}

这可能看起来很多,但请注意,它是可重用的通用代码,具有相当低的圈复杂度.

This may look like a lot, but notice that it's reusable, general-purpose code that has a rather low cyclomatic complexity.

您可以遵循相同的编码习惯来使用另一个 DI 容器或使用Poor Man's DI 来实现依赖注入.

You can follow the same coding idiom to implement Dependency Injection with another DI Container or by using Poor Man's DI.

这是一个 这个使用Poor Man's DI 的习语的较早的文章.

这篇关于将数据注入 WCF 服务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆