【问题标题】:How to get rid of ObjectFactory in code using StructureMap如何使用 StructureMap 在代码中摆脱 ObjectFactory
【发布时间】:2018-01-31 04:06:32
【问题描述】:

使用最新的 StructureMap 版本 (3.1.6.191) 升级我们的解决方案后,我收到了很多过时的警告。这些警告来自 StructureMap,其中 ObjectFactory 类将在未来的版本 (4.0+) 中被弃用。

我正在使用 WCF,我们希望使用 IInstanceProvider 的实现让 StructureMap 在 WCF 管道中挂钩:

public class StructureMapInstanceProvider : IInstanceProvider

这个类使用ObjectFactory来获取实例,当我的容器没有静态类来解析它的时候,我们如何获取一个类型的实例呢?

【问题讨论】:

    标签: c# wcf dependency-injection structuremap


    【解决方案1】:

    ObjectFactory 正在消失,因为许多人认为anti-pattern 从应用程序内部访问容器(称为服务定位器模式)。这将您的代码与容器紧密耦合,并且难以维护配置,因为确定类需要哪些依赖项并不容易。

    依赖注入不同于使用服务定位器。使用依赖注入,对象图在composition root 中的应用程序开始附近解析。一旦创建了应用程序,它就不会引用 IoC 容器,因此不会与它紧密耦合。依赖项在类构造函数中显式定义,因此您无需进一步查找类在注册时需要哪些依赖项。

    在运行时,您不可避免地需要创建类的实例。为此,您可以求助于众多 Creational Patterns 之一(其中最常见的是抽象工厂和 IInstanceProvider 实现),或者您可以使用容器来创建这些实例的 inject a method

    我推荐阅读本书Dependency Injection in .NET。有一节 (7.3) 通过实现 ServiceHostServiceHostFactoryIInstanceProvider,专门介绍了使用组合根连接 WCF。

    这是一个使用 StructureMap 的 WCF 组合根的基本示例(尽管我尚未验证它是否有效)。

    结构图注册表

    这里是您向容器注册类型的地方。如果您愿意,可以使用多个注册表。

    public class MyRegistry : Registry
    {
        public MyRegistry()
        {
            // Register all types
            this.For<ISomeService>().Use<SomeService>();
        }
    }
    

    服务主机工厂

    这是我们实例化容器并注册类型映射的地方。

    public class MyServiceHostFactory : ServiceHostFactory
    {
        private readonly IContainer container;
    
        public MyServiceHostFactory()
        {
            this.container = new Container(r => r.AddRegistry<MyRegistry>());
        }
    
        protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
        {
            return new MyServiceHost(this.container, serviceType, baseAddresses);
        }
    }
    

    服务主机

    这是我们注入容器的地方。是的,我们至少需要在一个地方这样做。在这里没问题,因为这都是要插入 WCF 的组合根的一部分。

    public class MyServiceHost : ServiceHost
    {
        public MyServiceHost(IContainer container, Type serviceType, params Uri[] baseAddresses)
            : base(serviceType, baseAddresses)
        {
            if (container == null)
                throw new ArgumentNullException("container");
    
            var contracts = this.ImplementedContracts.Values;
            foreach (var c in contracts)
            {
                c.Behaviors.Add(new MyInstanceProvider(container, serviceType));
            }
        }
    }
    

    IInstanceProvider

    再一次,我们仍处于应用程序的组合根目录中,因此我们可以注入容器来解析我们的实例。

    由此抽象工厂解析的服务不应具有对容器的引用(既不是静态的也不是注入的)。

    public partial class MyInstanceProvider : IInstanceProvider, IContractBehavior
    {
        private readonly IContainer container;
        private readonly Type serviceType;
    
        public MyInstanceProvider(IContainer container, Type serviceType)
        {
            if (container == null)
                throw new ArgumentNullException("container");
    
            this.container = container;
            this.serviceType = serviceType;
        }
    
        public object GetInstance(InstanceContext instanceContext, Message message)
        {
            return this.GetInstance(instanceContext);
        }
    
        public object GetInstance(InstanceContext instanceContext)
        {
            return this.container.GetInstance(this.serviceType);
        }
    
        public void ReleaseInstance(InstanceContext instanceContext, object instance)
        {
            // Allow the lifetime management behavior of StructureMap to release dependencies
        }
    
        public void ApplyDispatchBehavior(
            ContractDescription contractDescription, ServiceEndpoint endpoint,
            DispatchRuntime dispatchRuntime)
        {
            dispatchRuntime.InstanceProvider = this;
        }
    }
    

    用法

    只需将这些内容添加到您的 .svc 文件中即可注册自定义 MyServiceHostFactory 以解析您的 WCF 服务。

    <%@ ServiceHost Factory = "MyNamespaceName.MyServiceHostFactory, MyAssemblyName" Service = "MyNamespaceName.MyWcfService" %>
    

    参考文献:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-06
      • 1970-01-01
      • 2012-03-02
      • 1970-01-01
      • 2021-08-10
      相关资源
      最近更新 更多