Ian*_*ose 102 wcf dependency-injection factory-pattern
我想将值传递给实现我的服务的类的构造函数.
但是,ServiceHost只允许我传递要创建的类型的名称,而不是传递给其构造函数的参数.
我希望能够传入一个创建我的服务对象的工厂.
到目前为止我发现了什么:
Mar*_*ann 119
你需要实现自定义的组合ServiceHostFactory,ServiceHost和IInstanceProvider.
给定具有此构造函数签名的服务:
public MyService(IDependency dep)
Run Code Online (Sandbox Code Playgroud)
这是一个可以启动MyService的示例:
public class MyServiceHostFactory : ServiceHostFactory
{
private readonly IDependency dep;
public MyServiceHostFactory()
{
this.dep = new MyClass();
}
protected override ServiceHost CreateServiceHost(Type serviceType,
Uri[] baseAddresses)
{
return new MyServiceHost(this.dep, serviceType, baseAddresses);
}
}
public class MyServiceHost : ServiceHost
{
public MyServiceHost(IDependency dep, Type serviceType, params Uri[] baseAddresses)
: base(serviceType, baseAddresses)
{
if (dep == null)
{
throw new ArgumentNullException("dep");
}
foreach (var cd in this.ImplementedContracts.Values)
{
cd.Behaviors.Add(new MyInstanceProvider(dep));
}
}
}
public class MyInstanceProvider : IInstanceProvider, IContractBehavior
{
private readonly IDependency dep;
public MyInstanceProvider(IDependency dep)
{
if (dep == null)
{
throw new ArgumentNullException("dep");
}
this.dep = dep;
}
#region IInstanceProvider Members
public object GetInstance(InstanceContext instanceContext, Message message)
{
return this.GetInstance(instanceContext);
}
public object GetInstance(InstanceContext instanceContext)
{
return new MyService(this.dep);
}
public void ReleaseInstance(InstanceContext instanceContext, object instance)
{
var disposable = instance as IDisposable;
if (disposable != null)
{
disposable.Dispose();
}
}
#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
}
Run Code Online (Sandbox Code Playgroud)
在MyService.svc文件中注册MyServiceHostFactory,或直接在代码中使用MyServiceHost进行自托管方案.
您可以轻松地概括这种方法,事实上一些DI容器已经为您完成了这个(提示:Windsor的WCF工厂).
ker*_*rim 14
您可以简单地创建和实例化您的Service实例并将该实例传递给ServiceHost对象.您唯一需要做的就是为服务添加[ServiceBehaviour]属性并使用[DataContract]属性标记所有返回的对象.
这是一个模拟:
namespace Service
{
[ServiceContract]
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class MyService
{
private readonly IDependency _dep;
public MyService(IDependency dep)
{
_dep = dep;
}
public MyDataObject GetData()
{
return _dep.GetData();
}
}
[DataContract]
public class MyDataObject
{
public MyDataObject(string name)
{
Name = name;
}
public string Name { get; private set; }
}
public interface IDependency
{
MyDataObject GetData();
}
}
Run Code Online (Sandbox Code Playgroud)
和用法:
var dep = new Dependecy();
var myService = new MyService(dep);
var host = new ServiceHost(myService);
host.Open();
Run Code Online (Sandbox Code Playgroud)
我希望这会让某人的生活更轻松.
dal*_*alo 11
马克的回答IInstanceProvider是正确的.
您也可以使用自定义属性(例如MyInstanceProviderBehaviorAttribute),而不是使用自定义ServiceHostFactory .从中派生出来Attribute,使其实现IServiceBehavior并实现IServiceBehavior.ApplyDispatchBehavior类似的方法
// YourInstanceProvider implements IInstanceProvider
var instanceProvider = new YourInstanceProvider(<yourargs>);
foreach (ChannelDispatcher dispatcher in serviceHostBase.ChannelDispatchers)
{
foreach (var epDispatcher in dispatcher.Endpoints)
{
// this registers your custom IInstanceProvider
epDispatcher.DispatchRuntime.InstanceProvider = instanceProvider;
}
}
Run Code Online (Sandbox Code Playgroud)
然后,将该属性应用于您的服务实现类
[ServiceBehavior]
[MyInstanceProviderBehavior(<params as you want>)]
public class MyService : IMyContract
Run Code Online (Sandbox Code Playgroud)
第三个选项:您还可以使用配置文件应用服务行为.
我从马克的答案开始,但(至少在我的情况下),它是不必要的复杂.其中一个ServiceHost构造函数接受服务的实例,您可以直接从ServiceHostFactory实现传入该实例.
为了搭载Mark的例子,它看起来像这样:
public class MyServiceHostFactory : ServiceHostFactory
{
private readonly IDependency _dep;
public MyServiceHostFactory()
{
_dep = new MyClass();
}
protected override ServiceHost CreateServiceHost(Type serviceType,
Uri[] baseAddresses)
{
var instance = new MyService(_dep);
return new MyServiceHost(instance, serviceType, baseAddresses);
}
}
public class MyServiceHost : ServiceHost
{
public MyServiceHost(MyService instance, Type serviceType, params Uri[] baseAddresses)
: base(instance, baseAddresses)
{
}
}
Run Code Online (Sandbox Code Playgroud)