理解 Autofac 生命周期范围

6

根据Autofac的文档,我了解到它会保留创建的每个IDisposable实现者的引用。因此,它可能导致OutOfMemoryException。因此,建议使用ILifetimeScope来解决依赖关系。

假设IService实现了IDisposable接口。

class MaintenanceTask {
    private IService service;
    public MaintenanceTask(ILifetimeScope lifetimeScope) {
        service = lifetimeScope.Resolve<IService>();
    }
    //...do your work
}

但是这种方法的问题在于它隐藏了依赖关系。我必须查看代码才能确定该类依赖于什么。有没有其他更明确的处理方式?更具体地说,如何使依赖关系更加明显,而无需查看代码?或者我完全错了吗?

2个回答

6
传递一个生命周期范围就像传递容器本身。它类似于服务定位器(反-)模式,并且正如您所描述的那样存在问题:依赖关系变得不明显。
有一件事要问自己:
你真的有内存问题吗?如果没有,我就不会费心了。
另一个提示:
如果您有个别服务在使用后应立即处理,请使用工厂创建它们,并使您的类取决于工厂而不是服务本身。
生命周期范围的使用场景略有不同:
当您需要本地组合根时使用它们。在Windows应用程序中,我从未需要过这样的东西,但在Web应用程序中,会话或请求可能需要本地组合根。

我目前还没有遇到任何内存问题。我只是在预防未来可能出现的问题。我将在Windows应用程序+服务中使用autofac,所以不应该有什么麻烦。 - idursun
@idursun: 一般情况下,您不需要担心此问题。但是对于某些需要释放的个别服务,可以使用工厂进行处理。 - Daniel Hilgarth
1
注意,一个简单的替代工厂的方法是解决一个 Func<Owned<IService>>。这将为您提供一个工厂委托,该委托生成包含服务的可处置对象。这可以防止可处置服务被容器跟踪。 - Peter Lillevold
@PeterLillevold:你会把那个解析器放在哪里?如果你没有使用服务定位器反模式,你实际上不需要自己解析IService - Daniel Hilgarth
1
@DanielHilgarth:啊,是的,完全明白你的观点了。但是,如果你有这样的逻辑,比如一个“ServiceBuilder”,你可以注册它来创建“IService”实例,但仍然使用相同的“Func<Owned<IService>>”依赖项。 “MaintenanceTask”将继续不知道是谁产生了“IService”实例以及如何产生。 - Peter Lillevold
显示剩余5条评论

0

这个问题令我非常烦恼,以至于我创建了一个库来解决它。

请看Dependable

使用它后,您的代码将变为:

class MaintenanceTask {
    private IService service;
    public MaintenanceTask(IScopeFactory<IService> serviceFactory) {
        using(var serviceScope = serviceFactory.CreateScope())
        {
             service = serviceScope.Value;
             //...do your work
        }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接