【问题标题】:Autofac with self hosted WCF service and object disposal具有自托管 WCF 服务和对象处理的 Autofac
【发布时间】:2017-02-02 09:22:28
【问题描述】:

我通过利用 AutoFac 的 ServiceHost.AddDependencyInjectionBehavior() 扩展(如 Autofac documentation 中所述)将业务层注入到自托管(InstanceContextMode=per-call)WCF 服务中

我的业务层使用的组件在每次有新请求进入时都无法重新创建(假设它需要一个持久的数据库连接)。

因此,在构建容器时,我想将 BL 服务注册为单个实例,即:

builder.RegisterType<BusinessLayer>()
    .SingleInstance();

WCF 服务的业务层注入工作正常;我的问题是:

Dispose() 不会在容器中创建的任何服务上调用:不仅是业务层本身,还有“持久”服务。

我希望 BL 服务本身会发生这种情况。再次来自 Autofac docs

如果您有单例组件(注册为 SingleInstance())它们将在容器的整个生命周期中存在。由于容器生命周期通常是应用程序生命周期,它意味着组件 直到应用程序结束才会被释放。

,但是为什么我的“子”(Autofac 注册)服务(即下面的“IPersistentService”)在生命周期范围内没有被处理——因为我没有明确地将它们设为“SingleInstance”? 注意::关闭ServiceHost后,如果在生命周期范围内手动处置业务层服务,还是这样

例如(为简洁起见,省略了 IDisposable 实现):

[ServiceContract]
public interface IMyService
{
    void DoStuff();
}
public class MyService : IMyService
{
    IBusinessLayer _bl;
    public MyService(IBusinessLayer bl)
    {
        _bl = bl;
    }

    public void DoStuff()
    {
        _bl.BLDoStuff();
    }
}

public interface IBusinessLayer
{
    void BLDoStuff();
}
public class BusinessLayer : IBusinessLayer
{
    IPersistentService _service;
    public BusinessLayer(IPersistentService service)
    {
        _service = service;
    }
    public void BLDoStuff()
    {
        // Do something that requires a 'cached' / persistent component
        _service.DoSomethingWithPersistentConnection();
    }
}

public interface IPersistentService : IDisposable
{
    void DoSomethingWithPersistentConnection();
}

Autofac 注册看起来像这样:

builder.RegisterType<BusinessLayer>()
    .SingleInstance();

builder.RegisterType<MyPersistentService>()
    .As<IPersistentService>()
    .OnActivated(e => e.Instance.Start());

【问题讨论】:

  • “为什么我的 'child'(Autofac 注册)服务(即下面的 'IPersistentService')在生命周期范围为时没有被处理”。这个问题通常被称为Captive Dependency
  • 对。是的,这解释了它 - 并感谢该描述的链接。

标签: wcf autofac


【解决方案1】:

正如 Steven 所提到的,您在这里遇到的是 Captive Dependency 问题。换句话说,一个单例(BusinessLayer,注册到.SingleInstance())保持一个生命周期或瞬态依赖(MyPersistentService,默认注册为瞬态)。

这样说,单例服务的依赖永远都是单例,不管它们是如何在容器中注册的。 Steven 链接到的Mark Seeman's article 中的图表很好地说明了这一点。

我认为你可以达到你的期望,但是你的注册是错误的。

我的业务层使用的组件在每次有新请求进入时都无法重新创建(假设它需要一个持久的数据库连接)。

因此,在构建容器时,我想将 BL 服务注册为单个实例

这就是问题所在。必须将业务服务的依赖项注册为单例,而不是业务服务本身。这意味着您可以让 Autofac 为每个 WCF 调用创建一个不同的 BusinessLayer 实例,但注入的 MyPersistentService 实例总是相同的。这有意义吗?您的注册将如下所示:

builder
    .RegisterType<BusinessLayer>()
    .As<IBusinessLayer>()
    .InstancePerLifetimeScope(); // a new instance per WCF call

builder
    .RegisterType<MyPersistentService>()
    .As<IPersistentService>()
    .OnActivated(e => e.Instance.Start())
    .SingleInstance(); // one same instance for the lifetime of the application

只有在关闭服务主机后释放根容器(您通过调用 builder.Build() 创建的)之后,才会释放 MyPersistenService 的一个实例。

【讨论】:

  • 感谢您的解释——是的,正如@Steven 也提到的,所谓的“强制依赖”正是我的问题。然而,我真的很想利用 Autofac 的对象处理来清理“持久”服务。如果我将它们定义为单例,这听起来似乎是不可能的——因此我试图通过将 BL 服务改为单例来解决这个问题。
  • 我不明白。如果不能为每个请求重新创建持久化服务,那么为什么要在每个请求之后释放它呢?这对我来说听起来很矛盾。
  • 我不希望在每次请求后处理它们,而是在我关闭服务时处理它们。我的服务生命周期跨越了我的 WCF serviceHost 打开的持续时间。
  • ...我现在看到了我的问题实际上在哪里(尽管围绕强制依赖和每次调用重新创建的 BLService 实例的观点仍然非常正确)。我没有正确阅读文档:(。“如果您有单例组件(注册为 SingleInstance()),它们将在容器的生命周期内存活”。我以某种方式将其读作为 LifeTimeScope 的生命周期而活。我是'不处置容器...一旦我这样做了,单例实例(和所有子服务)就会正确处置。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-08
相关资源
最近更新 更多