我有像Miguel Castro建議的WCF服務。這意味着我已經手動設置了所有內容,並使用ServiceHost對象來託管我的服務。將數據注入WCF服務
我想保持我的服務類更加簡潔,他們目前只是將調用傳遞給行爲類。我現在的問題是單元測試服務類。我想向類中注入一些東西作爲構造函數參數,這樣我就可以將它嘲諷並編寫適當的單元測試。 ServiceHost類似乎不接受參數,所以我的問題是如何將數據注入服務類 - 或者我不能?
我有像Miguel Castro建議的WCF服務。這意味着我已經手動設置了所有內容,並使用ServiceHost對象來託管我的服務。將數據注入WCF服務
我想保持我的服務類更加簡潔,他們目前只是將調用傳遞給行爲類。我現在的問題是單元測試服務類。我想向類中注入一些東西作爲構造函數參數,這樣我就可以將它嘲諷並編寫適當的單元測試。 ServiceHost類似乎不接受參數,所以我的問題是如何將數據注入服務類 - 或者我不能?
WCF支持構造函數注入,但你必須通過幾個箍來到那裏。關鍵在於編寫一個自定義的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 Container或使用Poor Man的DI來實現依賴注入。
這是一個older writeup這個使用窮人的DI的成語。
您是否將您的服務配置爲Singleton?我發現使用DI容器創建服務實例時,IInstanceProvider實現可能會出現問題。
如果您使用的是Castle Windsor,它擁有一個很棒的WCF集成工具,可以讓您輕鬆做到這一點。
文章Hosting a Mock as a WCF service 包含一個靜態方法,該方法將根據傳遞給具有單個端點的方法的對象生成WCF服務主機。
該方法也發佈在的answer中。
使用示例調用NSubstitute,但可以使用其他嘲笑freameworks。
您使用的是IoC容器嗎?如果是的話,哪一個? – Fabiano 2010-01-11 16:35:47
我還沒有在服務器端使用IoC容器。計劃現在介紹一個。我在客戶端使用Unity(與Prism一起使用),但請考慮在服務器上使用StructureMap。爲任何人開放。 – stiank81 2010-01-11 17:59:47