如何递归遍历层次结构中的每个对象并删除所有事件引用

本文关键字:对象 删除 引用 事件 何递归 递归 层次结构 遍历 | 更新日期: 2023-09-27 18:01:08

我需要删除系统中每个对象的所有事件绑定。有成千上万的对象保存着事件,这导致了内存泄漏。我有一个严重的时间限制来排序,所以我想知道是否有一种方法可以递归地循环通过对象层次结构来删除事件绑定?

如何递归遍历层次结构中的每个对象并删除所有事件引用

注意:这都是真正的黑客行为,我不会容忍它的使用!

也就是说。。。是的,你可以。有点

假设你有一个类别Foo:

public class Foo
{
    public event EventHandler SomeEvent;
    public void Trigger()
    {
        if(SomeEvent != null)
        {
            SomeEvent(this, new EventArgs());
        }
    }
}

我们新建了其中一个,并以各种方式连接到活动:

public class Bar
{
    public Bar(Foo foo)
    {
        foo.SomeEvent += FooEvent;
    }
    public void FooEvent(object sender, EventArgs e)
    {
        Console.WriteLine("Bar.FooEvent!");
    }
}
var foo = new Foo();
var bar = new Bar(foo);
foo.SomeEvent += (o,e) => Console.WriteLine("SomeEvent");
Console.WriteLine("Normal");
foo.Trigger();

输出:

Normal
Bar.FooEvent!
SomeEvent

到目前为止一切正常,对吧?

现在-通过反射允许的肮脏:

首先,我们需要引用事件的EventInforemove方法:

var theFooEvent = foo.GetType().GetEvent("SomeEvent");
var theFooRemover = theFooEvent.GetRemoveMethod(true);

接下来,我们将稍微滥用Expressions来获得"现值":

var exp = 
    System.Linq.Expressions.Expression.PropertyOrField(
        System.Linq.Expressions.Expression.Constant(foo), 
        "SomeEvent");
var member = exp.Member;
var rtMember = (member as FieldInfo).GetValue(foo) as EventHandler;

我们已经走到了一半——现在要摧毁所有现有的处理程序:

var handlers = rtMember.GetInvocationList();
foreach(var handler in handlers)
{
    theFooRemover.Invoke(foo, new[] { handler });
}

那里。。。就是这样!进一步调用Trigger实际上不会有任何作用:

Console.WriteLine("Post hackery");
foo.Trigger();

输出:

Post hackery

讨厌。除非您知道事件处理程序的名称,否则使用反射看起来是不可能的;是否可以修改对象的Dispose方法以删除其成员的事件处理程序?