Autofac:如何限制一个IDisposable接口对象的生命周期没有通过周围的IoC容器 [英] Autofac: How to limit the lifetime of an IDisposable object without passing around the IoC container

查看:190
本文介绍了Autofac:如何限制一个IDisposable接口对象的生命周期没有通过周围的IoC容器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在学习如何使用Autofac和我卡与放置的IDisposable 确定性的对象。让我先介绍情况之前,我会说出我的问题。



起始位置:



比方说我对象模型是通过以下接口中定义的:

 接口IApple:IDisposable的
{
无效消费() ;
}

接口IHorse
{
无效吃(IApple苹果); //应该调用apple.Consume()
}

接口IHorseKeeper
{
无效FeedHorse(); //应该调用horse.Eat(苹果)
//其中马被注入IHorseKeeper
//和苹果是由IHorseKeeper上即时
}产生

此外,我定义将被用作 IApple 工厂:

 委托IApple AppleFactory; 



Autofac配置:



现在,我将登记上述类型如下 - 请注意,我省略这两个类的代码苹果,因为他们是微不足道的实施:

  VAR建设者=新Autofac.ContainerBuilder(); 

builder.RegisterType<苹果>()为<&IApple GT;();
builder.RegisterType<马>()为<&IHorse GT;();
builder.RegisterType< HorseKeeper>()为<&IHorseKeeper GT;();
builder.RegisterGeneratedFactory< AppleFactory>();



我的问题:



我不ŧ很知道如何实现方法 IHorseKeeper.Feed 。这是我目前有:

 类HorseKeeper:IHorseKeeper 
{
私人只读IHorse马;
私人只读AppleFactory appleFactory;

公共HorseKeeper(IHorse马,AppleFactory appleFactory)
// ^^^^^^^^^^^^ ^^^^^^^^^^^^^^^ ^^^^^^^^^^
//构造函数注入
{
this.horse =马;
this.appleFactory = appleFactory;
}

公共无效FeedHorse()
{
使用(VAR苹果= appleFactory())
{
horse.Eat(苹果);
} //< - 处置()现在苹果(ASAP),因为它不再需要!
}
}

这是我想有代码的那种,因为它是完全Autofac无关。它可能只是以及与其他IoC容器的工作,只要 AppleFactory 按预期工作。



不过,由于Autofac处理 AppleFactory 对我来说,它会跟踪所有的 IApple 对象,它产生了我,所以会想到的Dispose 他们本身在容器的生命周期结束。即,所生产的苹果将被全部销毁两次。



我猜想注册 IApple .ExternallyOwned()是没有可行的解决办法,因为可能有情况下,它更容易让Autofac处理 IApple s'的寿命。



确定性处置与Autofac 需要嵌套容器的使用创造 container.BeginLifetimeScope(),但是我不想用这里面 HorseKeeper.FeedHorse ,因为那时 HorseKeeper 变得依赖于Autofac,我想保持我的代码的IoC无关。



问:



我如何实施 HorseKeeper.FeedHorse 在IOC(Autofac而)-agnostic方式确保对即时生成的对象被妥善处理?


解决方案

在这里其他的答案是有见地的,但是有一个问题。在这两种情况下,如果苹果有需要处理的,正确的清理不会发生其他的依赖关系。



Autofac 2提供了一个新的功能,以帮助这里,所谓拥有实例 。我注意到,你的注册号为Autofac 1.4,因此,如果您无法升级让我知道(还有其他的,不太透明,如何做到这一点。)



注册苹果像往常一样(不是外部拥有):

  builder.RegisterType<苹果>()为< IApple>(); 



声明AppleFactory为:

 公共委托国有< IApple> AppleFactory(); 

在Autofac 2,你并不需要调用RegisterGeneratedFactory()了 - 这是自动

然后,在HorseKeeper,喂马是这样的:

 公共无效FeedHorse()
{
使用(VAR苹果= appleFactory())
{
horse.Eat(apple.Value);
}
}



(注意.Value属性来获取潜在的IApple



在使用阻止苹果,再加上其所有相关的结束,将被清理。



这是直接使用IApple(如依赖)任何其他组件将获得通常的行为。


I'm currently learning how to use Autofac, and I'm stuck with disposing IDisposable objects deterministically. Let me first present the situation before I'll state my problem.

Starting position:

Let's say my object model is defined through the following interfaces:

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
}

Further, I define a delegate that will be used as an IApple factory:

delegate IApple AppleFactory;

Autofac configuration:

Now, I would register the above types as follows -- note that I'm omitting the code of both classes Apple and Horse, since they're trivial to implement:

var builder = new Autofac.ContainerBuilder();

builder.RegisterType<Apple>().As<IApple>();
builder.RegisterType<Horse>().As<IHorse>();
builder.RegisterType<HorseKeeper>().As<IHorseKeeper>();
builder.RegisterGeneratedFactory<AppleFactory>();

My problem:

I don't quite know how to implement method IHorseKeeper.Feed. Here's what I currently have:

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!
    }
}

This is the kind of code I would like to have, as it's completely Autofac-agnostic. It could just as well work with another IoC container, as long as AppleFactory works as expected.

However, because Autofac handles the AppleFactory for me, it will keep track of all IApple objects it produces for me, and will therefore want to Dispose them itself at the end of the container's lifetime. Ie., the produced apple will be disposed twice.

I suppose registering IApple as .ExternallyOwned() is no viable solution, as there might be cases where it's easier to let Autofac handle the IApples' lifetime.

Deterministic disposal with Autofac requires the creation of a nested container using container.BeginLifetimeScope(), however I don't want to use this inside HorseKeeper.FeedHorse because then HorseKeeper becomes dependent on Autofac, and I would like to keep my code IoC-agnostic.

Question:

How do I implement HorseKeeper.FeedHorse in a IoC (Autofac)-agnostic way while ensuring that on-the-fly generated objects are disposed properly?

解决方案

The other answers here are insightful, but have a problem. In both cases, if Apple has other dependencies that need disposal, correct cleanup won't happen.

Autofac 2 provides a new feature to help here, called "owned instances". I noticed that your registration code is Autofac 1.4, so if you're unable to upgrade let me know (there are other, less transparent, ways to do this.)

Register Apple as usual (not externally owned):

builder.RegisterType<Apple>().As<IApple>();

Declare AppleFactory as:

public delegate Owned<IApple> AppleFactory();

In Autofac 2, you do not need to call RegisterGeneratedFactory() anymore - this is automatic.

Then, in HorseKeeper, feed the horse like this:

public void FeedHorse()
{
    using (var apple = appleFactory())
    {
        horse.Eat(apple.Value);
    }
}

(Note the .Value property to get the underlying IApple.

At the end of the using block the apple, plus all of its dependencies, will be cleaned up.

Any other components that use IApple directly (as dependencies) will get the usual behaviour.

这篇关于Autofac:如何限制一个IDisposable接口对象的生命周期没有通过周围的IoC容器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆