假设我有WeakReference
目标强引用。我希望在GC收集目标对象本身时得到通知。有可能吗?
编辑:在此处添加代码到终结器/析构函数不是一个选项。我需要的东西不依赖于类代码。
答案 0 :(得分:6)
可以在.NET 4.0下使用ConditionalWeakTable<TKey, TValue>
。感谢this和other个网站。它遵循概念代码的证明:
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);
}
}
}
}
使用以下代码进行测试:
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();
GC.WaitForPendingFinalizers();
}
}
答案 1 :(得分:2)
Object.Finalize()
方法怎么样?最终确定不会被调用吗?
答案 2 :(得分:0)
您可以使用拦截来捕获从自定义接口/类继承的每个类的Finalize。我想,这是你想要实现的目标,对吧?你可以使用Unity。 Here是一个非常简短的例子,说明如何用Unity进行拦截。