10

私は現在、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>();

私の問題:

method の実装方法がよくわかりません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 に完全に依存しないため、私が希望する種類のコードです。期待どおりに機能する限り、別の IoC コンテナーでも同様に機能しAppleFactoryます。

ただし、Autofac は私のために を処理するため、作成したすべてのオブジェクトAppleFactoryを追跡し、コンテナーの有効期間の終わりにそれら自体を必要とします。つまり、生成されたものは 2 回破棄されます。IAppleDisposeapple

Autofac にs の有効期間を処理させる方が簡単な場合があるため、 IAppleasとして登録することは実行可能な解決策ではないと思います。.ExternallyOwned()IApple

Autofacを使用した決定論的破棄には、 を使用してネストされたコンテナーを作成する必要がありますが、Autofac に依存するようになるため、container.BeginLifetimeScope()これを内部で使用したくありません。また、コードを IoC に依存しないようにしたいと考えています。HorseKeeper.FeedHorseHorseKeeper

質問:

HorseKeeper.FeedHorseオンザフライで生成されたオブジェクトが適切に破棄されるようにしながら、IoC (Autofac) に依存しない方法で実装するにはどうすればよいですか?

4

3 に答える 3

15

ここでの他の答えは洞察に満ちていますが、問題があります。どちらの場合も、Appleに廃棄が必要な他の依存関係がある場合、正しいクリーンアップは行われません。

Autofac 2は、「所有インスタンス」と呼ばれる、ここで役立つ新機能を提供します。登録コードがAutofac1.4であることに気づきました。アップグレードできない場合は、お知らせください(これを行うには、他にも透明性の低い方法があります)。

通常どおりAppleを登録します(外部所有ではありません):

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を取得するには、.Valueプロパティに注意してください。

使用ブロックの最後に、アップルとそのすべての依存関係がクリーンアップされます。

IAppleを直接(依存関係として)使用する他のコンポーネントは、通常の動作を取得します。

于 2010-02-14T00:39:32.607 に答える
3

ExternallyOwned唯一の方法は、修飾子を使用して Apple 登録を変更することです。これにより、Autofac は破棄のためにオブジェクトを追跡するのではなく、外部の誰か (コード) に破棄を処理させるように指示されます。しかし、あなたが述べたように、Autofac から自動的にヘルプが得られないため、Apple のすべてのインスタンスを手動で破棄する必要があります。

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

ただし、この登録により、フィード コードは期待どおりに機能します。

:インターフェイスが継承するかどうかの議論についてIDisposable:IMO、インターフェイスが継承する場合IDisposable、これは「消費する」開発者に対して、インスタンスをある時点で破棄する必要があることを示しています。IApple の場合、そのインターフェイスも IDisposable であるため、開発者はインスタンスを必ず破棄する必要があります (さらに、ExternallyOwned として登録する必要もあります)。一方、Apple クラスが次のようになっているとします。

class Apple: IApple, IDisposable
{ }

IApple の消費者は、インスタンスが IDisposable であるという事実をまったく認識していません。この場合、コンテナーに破棄を処理させます。

したがって、私の結論は、Apple と IApple の開発者である私が消費者に廃棄処理を要求するか、それともコンテナに任せるかを選択することです。

于 2010-02-13T14:49:55.250 に答える
2

Apple インスタンスの有効期間を自分で管理したい場合や、コンテナに処理させたい場合は、次の 2 つのインターフェイスを定義できます。

public IApple
{
   void Consume();
}

public IDisposableApple : IApple, IDisposable
{
}

そして、クラスを 2 回登録します。

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

その後、りんごを作成および破棄する必要があるクラスに DisposableAppleFactory を注入できます。

コンテナと同じ寿命を持つリンゴだけが必要なクラスでは、代わりに IApple を注入します。

ただし、両方が必要であるという事実は、newables と injectables を混合していることを示している可能性があります。Apple は、単純に「新しい」オブジェクト、つまり IoC コンテナによって管理される必要のないオブジェクトである可能性があります。

于 2010-02-13T15:40:22.753 に答える