在Windows.Forms应用程序中使用此处所述的弱事件http://wekempf.spaces.live.com/blog/cns!D18C3EC06EA971CF!373.entry时,WeakEventManager会泄漏WeakReference对象。 我认为这是因为没有WPF消息循环,所以从不执行CleanupOperation,尽管在WeakEventManager.ProtectedAddListener中调用了ScheduleCleanup。
作为一种解决方法,我实现了类似的清理功能:
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)使用反射。
所以我的问题是:
答案 0 :(得分: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();
}