5

ターゲットの強い参照のWeakReferenceがあるとします。ターゲットオブジェクト自体がGCによって収集されているときは、通知を受けたいと思います。出来ますか?GCでオブジェクトをフックすることはできますか?

EDIT:ファイナライザ/デストラクタへのコードの追加は、ここではオプションではありません。クラスコードに依存しないものが必要です。

+0

:次のコードでテスト

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Runtime.CompilerServices; namespace Test { public static class GCInterceptor { private static ConditionalWeakTable<object, CallbackRef> _table; static GCInterceptor() { _table = new ConditionalWeakTable<object, CallbackRef>(); } public static void RegisterGCEvent(this object obj, Action<int> action) { CallbackRef callbackRef; bool found = _table.TryGetValue(obj, out callbackRef); if (found) { callbackRef.Collected += action; return; } int hashCode = RuntimeHelpers.GetHashCode(obj); callbackRef = new CallbackRef(hashCode); callbackRef.Collected += action; _table.Add(obj, callbackRef); } public static void DeregisterGCEvent(this object obj, Action<int> action) { CallbackRef callbackRef; bool found = _table.TryGetValue(obj, out callbackRef); if (!found) throw new Exception("No events registered"); callbackRef.Collected -= action; } private class CallbackRef { private int _hashCode; public event Action<int> Collected; public CallbackRef(int hashCode) { _hashCode = hashCode; } ~CallbackRef() { Action<int> handle = Collected; if (handle != null) handle(_hashCode); } } } } 

:それは概念実証コードを次の。あなたが試みるかもしれない最も近いものは、コレクションが発生する前に不特定の時間前に実行されますが、参照されている型のファイナライザを作成することです。私は誰かがよりスマートに答えを出すのを楽しみにしています。 –

+3

ガベージコレクタがオブジェクトを破棄すると、オブジェクトのデストラクタが呼び出されます。あなたはデストラクタコールで反応して、例えば自分で作られたイベントを送ることができます。 –

+1

復活のためのレシピのように聞こえる。なぜこれが必要ですか? – Ani

答えて

5

ConditionalWeakTable<TKey, TValue>を使用して.NET 4.0以降で使用することは可能です。ありがとうございましたthisotherサイト。私はアドレスが収集されていることを示し発生したすべてのイベントがあります信じていません

public partial class Form1 : Form 
{ 
    private object _obj; 

    public Form1() 
    { 
     InitializeComponent(); 

     _obj = new object(); 

     _obj.RegisterGCEvent(delegate(int hashCode) 
     { 
      MessageBox.Show("Object with hash code " + hashCode + " recently collected"); 
     }); 
    } 

    private void button1_Click(object sender, EventArgs e) 
    { 
     _obj = null; 
     GC.Collect(); 
    } 
} 
2

Object.Finalize()についてはどうすればよいですか?ファイナライズ時に呼び出されませんか?

+0

これは正しいです。デストラクタは暗黙的に 'Object.Finalize()'を呼び出すので、このメソッドをオーバーライドしてここからシグナリングすると、オブジェクトがガベージコレクションされた正確な時刻が得られます。 –

+0

申し訳ありませんが、私はより透明で、クラスコードに依存しない何かが必要です。たぶんそれは可能ではないかもしれません。 – ceztko

+1

これは、通常、Disposeable型の場合のように、 'GC.SupressFinalize'の呼び出しが行われない限り動作します。さらに、ファイナライザがガベージコレクション中に実行する正確な時刻は定義されていません。 –

0

カスタムインターフェイス/クラスから継承したクラスごとに、インターセプトを使用してFinalizeをキャッチできます。私はこれがあなたが達成しようとしているものだと思いますよね?そのためにUnityを使うことができます。 Hereは、Unityとの傍受を行う方法の非常に短い例です。

+0

正しい(実際にはインターフェイスなので、基本クラスのファイナライザでコードを書くことができない理由が説明されています)。 Unity 3.5は.NET 3.5に組み込まれていますか? – ceztko

+0

[こちら](http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=15104)によれば、.NET 3.5 SP1もサポートしています。しかし、私は.NET 4.0で使っています。また、ウェブにはIoCライブラリがあります。しかし、私はUnityがより堅牢なソリューションであることを発見しました。 –

+0

私はそれを調べています。それは良いと簡単な解決策かもしれません。 – ceztko

関連する問題