2

私のコントローラーは、IDisposable を実装するフィールドを含むクラスから継承します。だから私の最初の本能は書くことでした:

public abstract class EventRepositoryControllerBase : Controller
{
    protected EventRepository eventRepos { get; private set; }

    public EventRepositoryControllerBase(EventRepository eventRepos)
    {
        this.eventRepos = eventRepos;
    }

    public override void Dispose()
    {
        try
        {
            base.Dispose();
        }
        finally
        {
            eventRepos.Dispose();
        }
    }
}

ただし、コントローラーは Dispose メソッドを仮想/オーバーライドとしてマークしていないため、これはコンパイルされません。だから今、私は立ち往生していると思います。メソッドを新規としてマークしても、フレームワークは Controller として型指定された参照を保持しないので、メソッドが呼び出されることはありませんか? これを回避する方法に関する提案はありますか?

アップデート

だから私はMVC3ソースを見て、これを見ました:

 public void Dispose() {
        Dispose(true /* disposing */);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing) {
    }

だから私は自分のコードを2番目の方法に入れるだけだと思います。ただし、この動作が契約で指定されているかどうかはわかりません。

4

3 に答える 3

0

ASP.NET MVC のコントローラー クラスには、IDisposable インターフェイスが正しく実装されています。詳細については、これを正確に指定している MSDN ページのこのページを確認してください。

IDisposible インターフェイスにプラグインするには、把握した保護された dispose メソッドをオーバーライドし、そこに「独自の」クラスを破棄するロジックを配置する必要があります。

于 2012-05-24T04:32:30.573 に答える
0

封印されていないメソッドで実装された場合IDisposable.Dispose、派生型のコードは基本型のクリーンアップ コードの前後に実行されます。はGC.SuppressFinalize、派生型がクリーンアップを完了するまで (基本型がクリーンアップを完了した後に発生する可能性がある部分を含む) 呼び出されるべきではないためGC.SuppressFinalize、シールされた実装で作成され、署名が次の仮想メソッドを呼び出します。void Dispose(bool).

概念的には、封印されたラッパー内で仮想メソッドを呼び出すことは良い考えですが、Microsoft の実装にはいくつかの欠陥があることに注意してください。最も注目すべき点:

  1. 基本クラスでプライベート フラグを使用して、オブジェクトがまだ破棄されているかどうかを示しますが、ラッパー メソッドではそのフラグを使用しないため、重複した破棄を回避したいすべての派生クラスは、独自の破棄フラグも持つ必要があります。
  2. 派生した `Dispose` 呼び出しが終了するシナリオは 3 つあります。
    1. 正常に戻る可能性があります
    2. 例外をスローする可能性がありますが、ファイナライズが抑制されるように、達成可能なすべてのことを達成しています (たとえば、'IDisposable' ロギング オブジェクトがファイルをラップし、ファイル データがクロージャで正常に書き込まれなかった場合など)。醜い状況ですが、ファイナライズのためにオブジェクトを登録したままにしておくことは役に立ちません。
    3. オブジェクトがファイナライズの資格を維持する必要があるシナリオでは、例外がスローされる可能性があります。
    Microsoft の「Dispose」パターンは、後者の 2 つの選択肢を区別する手段を提供しません。ファイナライズ ベースのクリーンアップのためにオブジェクトを登録したままにしておくことは、多くの場合無害ですが、Finalize メソッドを使用して Dispose の呼び出しの失敗をログに記録すると、混乱を招く可能性があります。
  3. これは、オブジェクトが多くの場合、ファイナライズによってクリーンアップするリソースと、「Dispose」によってのみクリーンアップされるリソースを保持する必要があることを意味します。実際には、ファイナライザを持つクラスは、ファイナライズに不要なオブジェクトへの参照を保持しないようにする必要があります。ファイナライズが必要なリソースは、独自のクラス オブジェクトにカプセル化する必要があります。これは、ファイナライズについて心配する必要のないクラスによって保持される必要があります。

Microsoft が管理されていないリソースを処理する最善の方法を見つける前に、このDisposeパターンは最初の優れた取り組みでした。今日、仮想メソッドのパラメーターは、意味のあるものとしてではなく、署名を変更するために使用されるダミーパラメーターであると見なす方がよいと思います (ただしTrue、ラッパーから仮想メソッドをチェーンするときは常に渡す必要があります)。

于 2012-05-24T15:15:45.533 に答える
-1

1)現在のクラスにidisposableインターフェースを実装し、やりたいことを実行します2)そのインターフェースを基本クラスに実装し、このクラスでオーバーライドします3)基本クラスにそのインターフェースのみを実装し、オーバーライドしないでくださいまた、あなたのコードは奇妙に思えます。抽象クラスがあり、実装ロジックを提供しています

于 2012-05-24T04:35:10.637 に答える