3

ここで説明されているように弱いイベントを使用する場合http://wekempf.spaces.live.com/blog/cns!D18C3EC06EA971CF!373.entryWindows.FormsアプリケーションでWeakEventManagerがWeakReferenceオブジェクトをリークします。これは、WPFメッセージループがないと、ScheduleCleanupがWeakEventManager.ProtectedAddListenerで呼び出されても、CleanupOperationが実行されないためだと思います。

回避策として、次のようなクリーンアップ関数を実装しました。

internal bool Cleanup()
{
    // The following is equivalent to 
    //    return this.Table.Purge(false);
    // but we need to use reflection to access the private members.

    PropertyInfo pi = typeof(WeakEventManager).GetProperty("Table", BindingFlags.Instance | BindingFlags.NonPublic);
    if (pi == null)
        return false;
    object table = pi.GetValue(this, null);
    MethodInfo mi = table.GetType().GetMethod("Purge", BindingFlags.Instance | BindingFlags.NonPublic);
    if (mi == null)
        return false;
    return (bool)mi.Invoke(table, new object[] { false });
}

たとえば、への16回目の呼び出しごとにこれを呼び出しますProtectedAddListener

これは機能しますが、明らかに私はこの(乱用された)反射の使用を避けたいと思っています。

だから私の質問は:

  1. パブリック/保護されたメンバーを使用してクリーンアップ機能を実装する方法はありますか?WeakEventManager.Purgeは便利かもしれませんが、使い方がわかりません。
  2. Windows.FormsベースのアプリケーションでWPFメッセージループを実行する簡単な方法はありますか?
4

1 に答える 1

2

このコードは、キャッシュを保持できる静的関数を構築します。それが実行されるたびにリフレクションの苦痛を取り除き、本質的にあなたが持っていたものだけを行います。どこかにキャッシュし、毎回弱いイベント マネージャーを渡して呼び出します。1 回限りのヒット (ビルド/コンパイル時) を除いて、それ以上のリフレクションはありません。

    using System.Windows;
    using System.Linq.Expressions;
    using Expression = System.Linq.Expressions.Expression;

    static void Main(string[] args)
    {
        Func<WeakEventManager, bool> cleanUpFunction = BuildCleanUpFunction();
    }

    private static Func<WeakEventManager, bool> BuildCleanUpFunction()
    {
        ParameterExpression managerParameter = Expression.Parameter(
            typeof(WeakEventManager),
            "manager"
        );
        return Expression.Lambda<Func<WeakEventManager, bool>>(
            Expression.Call(
                Expression.Property(
                    managerParameter,
                    "Table"
                ),
                "Purge",
                Type.EmptyTypes,
                Expression.Default(
                    typeof(bool)
                )
            ),
            managerParameter
        ).Compile();
    }
于 2011-02-23T20:27:45.517 に答える