我读了Jimmy Bogard的这篇文章,我明白了如何在服务上创建依赖注入。我读了这两篇文章:http://blogs.planbsoftware.co.nz/?p=492和http://lostechies.com/jimmybogard/2008/07/30/integrating-structuremap-with-wcf/。
所以我在阅读文章之后的问题是,在哪里编写那里描述的那些类(StructureMapInstanceProvider,StructureMapServiceBehavior,StructureMapServiceHost,StructureMapServiceHostFactory)。我应该在服务上还是在服务主机上写这些内容?另一个问题是在哪里配置服务?在主机的global.asax中,还是在服务的global.asax上?
有人可以解释一下吗?
答案 0 :(得分:1)
一起讨论WCF和StructureMap的文章比较古老。我创建了一个使用WCF和StructureMap的最小应用程序,可以在GitHub上找到它。
WCF通过IInstanceProvider
接口创建实例,因此我们需要创建一个自定义实例提供程序,该提供程序通过StructureMap创建实例。该实例提供者使用容器来解析请求的类型:
public class StructureMapInstanceProvider : IInstanceProvider
{
private readonly IContainer _container;
private readonly Type _type;
public StructureMapInstanceProvider(IContainer container, Type type)
{
_container = container;
_type = type;
}
public object GetInstance(InstanceContext instanceContext)
{
return _container.GetInstance(_type);
}
public object GetInstance(InstanceContext instanceContext, Message message)
{
return GetInstance(instanceContext);
}
public void ReleaseInstance(InstanceContext instanceContext, object instance)
{
_container.Release(instance);
}
}
通过设置InstanceProvider
类的DispatchRuntime
,每个端点可以拥有自己的实例提供程序。这通常是完成的。通常是在IServiceBehavior
中的服务行为(ApplyDispatchBehavior
)内部完成的。
public class StructureMapServiceBehavior : IServiceBehavior
{
private readonly IContainer _container;
public StructureMapServiceBehavior(IContainer container)
{
_container = container;
}
public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
}
public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
{
}
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
foreach (var channelDispatcher in serviceHostBase.ChannelDispatchers.OfType<ChannelDispatcher>())
{
foreach (var ed in channelDispatcher.Endpoints)
ed.DispatchRuntime.InstanceProvider = new StructureMapInstanceProvider(_container, serviceDescription.ServiceType);
}
}
}
该行为需要添加到ServiceHost
中,以便将其应用于该主机内的所有服务:
serviceHost.Description.Behaviors.Add(new StructureMapServiceBehavior(container));
现在将通过StructureMap创建服务,您可以在服务中使用依赖项注入。此解决方案不使用任何静态变量或工厂模式(如我所见的其他一些示例所示)。
当服务的InstanceContextMode
设置为PerCall
或PerSession
时,您可能需要嵌套容器。您需要在IInstanceProvider.GetInstance
调用中创建这些嵌套容器,并将嵌套容器放置在IInstanceProvider.ReleaseInstance
中。为了确保您可以关联GetInstance
和ReleaseInstance
,可以将其他信息添加到实例上下文中(通过Extensions
属性。您可以在此commit中找到所需的更改
在ServiceHost
的构造函数中已经创建了单例,因此您不能使用行为来更改创建。如果单例具有默认构造函数(并且IoC服务通常不具有这些构造函数),则只能在WCF中创建它们。如果要将服务主机与StructureMap和单例一起使用,则可以将单例直接传递到容器:
using (var container = Register())
{
var singleton = container.Resolve<HelloWcfServer>();
using (var host = new ServiceHost(singleton, Settings.BaseUri))
{
// ...
}
}