gpt4 book ai didi

c# - 如何使用 StructureMap 摆脱代码中的 ObjectFactory

转载 作者:行者123 更新时间:2023-11-30 14:08:52 26 4
gpt4 key购买 nike

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

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

public class StructureMapInstanceProvider : IInstanceProvider

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

最佳答案

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

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

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

我推荐阅读这本书 Dependency Injection in .NET .有一个部分 (7.3) 专门介绍了通过实现 ServiceHostServiceHostFactoryIInstanceProvider 将 WCF 与组合根连接起来。

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

StructureMap 注册表

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

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);
}
}

服务主机

这是我们注入(inject)容器的地方。是的,我们至少需要在一个地方这样做。在这里没问题,因为这是插入 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

我们仍然处于应用程序的组合根中,因此我们可以注入(inject)容器来解析我们的实例。

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

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" %>

使用的引用资料:

关于c# - 如何使用 StructureMap 摆脱代码中的 ObjectFactory,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32732650/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com