【发布时间】:2010-02-13 13:04:58
【问题描述】:
我目前正在学习如何使用 Autofac,但我一直坚持以确定性方式处理 IDisposable 对象。在我陈述我的问题之前,让我先介绍一下情况。
起始位置:
假设我的对象模型是通过以下接口定义的:
interface IApple : IDisposable
{
void Consume();
}
interface IHorse
{
void Eat(IApple apple); // is supposed to call apple.Consume()
}
interface IHorseKeeper
{
void FeedHorse(); // is supposed to call horse.Eat(apple)
// where 'horse' is injected into IHorseKeeper
// and 'apple' is generated by IHorseKeeper on-the-fly
}
此外,我定义了一个将用作IApple 工厂的委托:
delegate IApple AppleFactory;
Autofac 配置:
现在,我将按如下方式注册上述类型 - 请注意,我省略了 Apple 和 Horse 两个类的代码,因为它们实现起来很简单:
var builder = new Autofac.ContainerBuilder();
builder.RegisterType<Apple>().As<IApple>();
builder.RegisterType<Horse>().As<IHorse>();
builder.RegisterType<HorseKeeper>().As<IHorseKeeper>();
builder.RegisterGeneratedFactory<AppleFactory>();
我的问题:
我不太清楚如何实现方法IHorseKeeper.Feed。这是我目前拥有的:
class HorseKeeper : IHorseKeeper
{
private readonly IHorse horse;
private readonly AppleFactory appleFactory;
public HorseKeeper(IHorse horse, AppleFactory appleFactory)
// ^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^
// constructor injection
{
this.horse = horse;
this.appleFactory = appleFactory;
}
public void FeedHorse()
{
using (var apple = appleFactory())
{
horse.Eat(apple);
} // <- Dispose() apple now (ASAP), as it's no longer needed!
}
}
这是我想要的那种代码,因为它完全与 Autofac 无关。只要AppleFactory 按预期工作,它也可以与另一个 IoC 容器一起工作。
但是,由于 Autofac 为我处理 AppleFactory,它会跟踪它为我生成的所有 IApple 对象,因此在容器的生命周期结束时会希望 Dispose 它们自己。即产生的apple会被处理两次。
我认为将 IApple 注册为 .ExternallyOwned() 不是可行的解决方案,因为在某些情况下,让 Autofac 处理 IApples 的生命周期可能更容易。
Deterministic disposal with Autofac 需要使用container.BeginLifetimeScope() 创建一个嵌套容器,但是我不想在HorseKeeper.FeedHorse 中使用它,因为那时HorseKeeper 变得依赖于 Autofac,我想保留我的代码 IoC - 不可知论者。
问题:
如何以与 IoC (Autofac) 无关的方式实现 HorseKeeper.FeedHorse,同时确保正确处理动态生成的对象?
【问题讨论】:
-
我不能具体说明如何使用 Autofac 解决这个问题,但总的来说,让 IApple 从 IDisposable 派生是一个泄漏抽象。你最好重新考虑你的设计。
-
@Mark Seemann,我很想知道为什么
IApple也不需要实现类来实现IDisposable。一个简短的解释将不胜感激。 -
为什么要这样?实现 IDisposable 向运行时以及其他开发人员表明所讨论的类型包含对非托管内存的引用。在接口的情况下,这根本是不可能的,因此它表明您正在让您对一个或多个具体实现的了解泄漏到抽象中。
-
另外,看看 Nicholas Blumhardt 在 2 月 4 日凌晨 5:10 的讨论中的 cmets:cca.codeplex.com/Thread/View.aspx?ThreadId=82987 总结得很好。
-
好的,谢谢。以后我会牢记这一点! (但是,我仍然不同意
IDisposable仅用于释放非托管资源。实施IDisposableIMO 还有其他正当理由。)
标签: c# inversion-of-control dispose idisposable autofac