3

当在 Windows.Forms 应用程序中使用此处描述的弱事件http://wekempf.spaces.live.com/blog/cns!D18C3EC06EA971CF!373.entry时,WeakEventManager 会泄漏 WeakReference 对象。我认为这是因为如果没有 WPF 消息循环,则永远不会执行 CleanupOperation,尽管在 WeakEventManager.ProtectedAddListener 中调用了 ScheduleCleanup。

作为一种解决方法,我实现了一个 Cleanup 函数,如下所示:

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.

这行得通,但显然我喜欢避免这种(ab)使用反射。

所以我的问题是:

  1. 有没有办法使用公共/受保护的成员来实现清理功能?WeakEventManager.Purge 可能有用,但我不知道如何使用它。
  2. 有没有一种简单的方法可以在基于 Windows.Forms 的应用程序中运行 WPF 消息循环?
4

1 回答 1

2

此代码构建了一个静态函数,您可以保持缓存。它将消除每次运行时反射的痛苦,并且基本上做你所拥有的。将其缓存在某处并通过每次传入您的弱事件管理器来调用它。除了一次性命中(在构建/编译期间),没有进一步的反射。

    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 回答