2

多くのイベントを使用する C# (.NET 4.6.1) プロジェクトがあります。私はすべてのイベント ハンドラーを新しい WeakEventManager パターンに移動したいと思っています。これは、メモリー リークを回避するためにハンドラーの登録解除について果てしなく心配することを避けるためです。

ただし、パフォーマンスについて多くのテストを行う必要があり、2 つの方法を簡単に切り替える方法が必要です。これまでのところ、次の行に沿ってこれを行うために条件付きコンパイルを使用してきました。

#if WeakEvents
    WeakEventManager<EventSource,EArgs>.AddHandler(source, "TheEvent", handler);
#else
    source.TheEvent += handler;
#endif

これは機能しますが、面倒です。理想的には、これを隠すクラスを作成したいと思います。つまり、いずれかのメソッドを内部的に使用できるクラスを作成します。次に、すべてのソースを変更して、ハンドラーを新しいクラスにアタッチし、簡単に切り替えることができます (または、将来的に新しいメソッドに移動することもできます)。

ただし、イベントをパラメーターとして渡すことができないため、そのクラスの記述方法がわかりません。また、ハンドラー/名前で何らかのリフレクションが行われる必要がありますが、これは私を超えています。

それを行う簡単な方法はありますか?

4

1 に答える 1

1

これを行う 1 つの方法を次に示します。

static class EventHelper {
    public static void Subscribe<TSource, TEventArgs>(TSource source, Expression<Func<TSource, EventHandler<TEventArgs>>> eventRef, EventHandler<TEventArgs> handler) where TEventArgs : EventArgs {
        if (source == null)
            throw new ArgumentNullException(nameof(source));
        var memberExp = eventRef.Body as MemberExpression;
        if (memberExp == null)
            throw new ArgumentException("eventRef should be member access expression");

        var eventName = memberExp.Member.Name;
    #if WeakEvents
        WeakEventManager<TSource, TEventArgs>.AddHandler(source, eventName, handler);            
    #else
        // some reflection here to get to the event
        var ev = source.GetType().GetEvent(eventName);
        if (ev == null)
            throw new ArgumentException($"There is no event with name {eventName} on type {source.GetType()}");
        ev.AddMethod.Invoke(source, new object[] { handler });
    #endif
    }
}

使い方は次のように簡単です。

// second parameter is event reference
EventHelper.Subscribe(source, s => s.TheEvent, Handler);
于 2016-10-30T20:24:53.403 に答える