起始位置:
假设我的对象模型是通过以下接口定义的:
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;
自动配置配置:
现在,我将注册以上类型如下 – 请注意,我省略了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-agnostic.只要AppleFactory可以按预期工作,它可以与另一个IoC容器一起工作.
然而,由于Autofac为我处理AppleFactory,它将跟踪它为我生成的所有IApple对象,因此将在容器的生命周期结束时自己处理它们.也就是说,生产的苹果将被处理两次.
我想将IApple注册为.ExternallyOwned()不是可行的解决方案,因为可能会更容易让Autofac处理IApples的生命周期.
Deterministic disposal with Autofac需要使用container.BeginLifetimeScope()创建一个嵌套的容器,但是我不想在HorseKeeper.FeedHorse中使用它,因为这样HorseKeeper将依赖于Autofac,我想保持我的代码IoC-agnostic.
题:
如何在IoC(Autofac)诊断方式下实现HorseKeeper.FeedHorse,同时确保即时生成的对象被正确放置?
解决方法
Autofac 2提供了一个新的功能来帮助这里称为“拥有的实例”.我注意到你的注册码是Autofac 1.4,所以如果你无法升级让我知道(还有其他的,透明度较低的方法)
像往常一样注册苹果(不是外部拥有的):
builder.RegisterType<Apple>().As<IApple>();
将AppleFactory声明为:
public delegate Owned<IApple> AppleFactory();
在Autofac 2中,您不需要再调用RegisterGeneratedFactory() – 这是自动的.
然后,在HorseKeeper,喂马像这样:
public void FeedHorse() { using (var apple = appleFactory()) { horse.Eat(apple.Value); } }
在使用块的末尾,苹果加上其所有依赖项,将被清理掉.
直接使用IApple(作为依赖)的任何其他组件将获得通常的行为.