1

我需要删除系统中每个对象的所有事件绑定。有数千个对象正在保存事件,这会导致内存泄漏。我在严重的时间限制下进行排序,所以我想知道是否有一种方法可以递归地循环遍历对象层次结构以删除事件绑定?

4

2 回答 2

1

注意:这都是非常骇人听闻的东西,我不容忍它的使用!

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

假设你有一堂课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
于 2013-02-26T17:55:42.647 回答
0

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

于 2013-02-26T17:07:13.613 回答