c# – Autofac:如何限制IDisposable对象的生命周期,而不会绕过IoC容器

我正在学习如何使用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;

自动配置配置:

现在,我将注册以上类型如下 – 请注意,我省略了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);
    }
}

(注意.Value属性获取底层的IApple.

在使用块的末尾,苹果加上其所有依赖项,将被清理掉.

直接使用IApple(作为依赖)的任何其他组件将获得通常的行为.

相关文章

在要实现单例模式的类当中添加如下代码:实例化的时候:frmC...
1、如果制作圆角窗体,窗体先继承DOTNETBAR的:public parti...
根据网上资料,自己很粗略的实现了一个winform搜索提示,但是...
近期在做DSOFramer这个控件,打算自己弄一个自定义控件来封装...
今天玩了一把WMI,查询了一下电脑的硬件信息,感觉很多代码都...
最近在研究WinWordControl这个控件,因为上级要求在系统里,...