数据注入到WCF服务数据、WCF

2023-09-02 10:19:55 作者:最可爱的猪

我已经WCF结构服务,如通过米格尔·卡斯特罗建议。这意味着我已经设置好一切手动,并有一个控制台应用程序中使用托管服务,我的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.

作为一个例子,我最近写了一个使用温莎城堡要连接的依赖关系为服务实现。 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
}

这看起来好像很多,但是请注意,它是可重用的,通用的code,有一个相当低的圈复杂度。

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

您可以按照相同的编码成语来实现依赖注入与其他DI容器或用穷人的DI。

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

下面是一个older这个成语使用穷人的DI的书面记录。

 
精彩推荐
图片推荐