我已经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的书面记录。