1

システム内のすべてのオブジェクトのすべてのイベント バインディングを削除する必要があります。イベントを保持している何千ものオブジェクトがあり、これがメモリ リークを引き起こしています。私はこれをソートするために深刻な時間的制約を受けているので、オブジェクト階層を再帰的にループしてイベントバインディングを削除する方法があるかどうか疑問に思っていますか?

4

2 に答える 2

1

注: これはすべて本当にハックなものであり、私はその使用を容認しません!

そうは言っても...ええ、できます。ちょっと。

あなたがクラスを持っているとしましょうFoo

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

これらの 1 つを新たに作成し、さまざまな方法でイベントに接続します。

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

これまでのところ、すべて正常ですよね?

今 - リフレクションを介して許容される厄介さ:

まず、イベントのEventInfoおよびremoveメソッドへの参照が必要です。

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 に答える