使用WCF为IoC配置StructureMap(依赖注入)

时间:2014-10-21 06:54:29

标签: c# wcf structuremap configure

我读了Jimmy Bogard的这篇文章,我明白了如何在服务上创建依赖注入。我读了这两篇文章:http://blogs.planbsoftware.co.nz/?p=492http://lostechies.com/jimmybogard/2008/07/30/integrating-structuremap-with-wcf/

所以我在阅读文章之后的问题是,在哪里编写那里描述的那些类(StructureMapInstanceProvider,StructureMapServiceBehavior,StructureMapServiceHost,StructureMapServiceHostFactory)。我应该在服务上还是在服务主机上写这些内容?另一个问题是在哪里配置服务?在主机的global.asax中,还是在服务的global.asax上?

有人可以解释一下吗?

1 个答案:

答案 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设置为PerCallPerSession时,您可能需要嵌套容器。您需要在IInstanceProvider.GetInstance调用中创建这些嵌套容器,并将嵌套容器放置在IInstanceProvider.ReleaseInstance中。为了确保您可以关联GetInstanceReleaseInstance,可以将其他信息添加到实例上下文中(通过Extensions属性。您可以在此commit中找到所需的更改

单人服务(餐厅)

ServiceHost的构造函数中已经创建了单例,因此您不能使用行为来更改创建。如果单例具有默认构造函数(并且IoC服务通常不具有这些构造函数),则只能在WCF中创建它们。如果要将服务主机与StructureMap和单例一起使用,则可以将单例直接传递到容器:

using (var container = Register())
{
    var singleton = container.Resolve<HelloWcfServer>();
    using (var host = new ServiceHost(singleton, Settings.BaseUri))
    {
         // ...
    }
}