【问题标题】:How to add an event handler exactly once, if it doesn't exists如果事件处理程序不存在,如何仅添加一次
【发布时间】:2013-11-20 17:27:38
【问题描述】:

我需要在我的集合更改时添加和删除事件处理程序:

public void SetStorageProviderFor<T>(Expression<Func<T, object>> expr, IStorageProvider sp) where T : class
{
    MemberExpression me = (MemberExpression)expr.Body;
    Set<T>().Local.CollectionChanged +=
        (sender, args) =>
        {
            foreach (var item in args.NewItems)
            {
                // get entity's property on member expression and set its value
            }
        }
}
  1. 如何防止添加相同的处理程序?
  2. 如何删除某些特定的处理程序?我认为我不应该重复所有相同的代码,但要使用“-=”标记...
    我还尝试将处理程序设置为 Action 以将其存储在内存中,并随时从 CollectionChanged 取消分配:

    Action<object, NotifyCollectionChangedEventArgs> act = (sender, args) => { }

但是CollectionChanged 不能接受这个动作作为处理程序:(
感谢您提供任何帮助。
更新
抱歉,我应该发布更多真实代码。问题是我的处理程序使用的参数不仅仅是CollectionChanged,还需要SetStorageProviderFor 方法的exprsp。在这种情况下,我可以创建命名方法作为 Tim S. 建议,但如果我为它提供额外的参数,那么我将无法直接将其分配给 Set&lt;T&gt;().Local.CollectionChanged,将再次需要匿名 lambda;(

【问题讨论】:

  • 1, 2.a, 2.b
  • 你可能想试试这个CollectionChangedEventHandler&lt;object, NotifyCollectionChangedEventArgs&gt; act = (sender, args) =&gt; { };
  • @KingKing 刚试过Set&lt;T&gt;().Local.CollectionChanged += (NotifyCollectionChangedEventHandler)act,它说无法投射
  • @KingKing "Delegate CollectionChangedEventHandler 没有类型参数"
  • @jim 那么Local 的类型是什么?

标签: c# .net oop events


【解决方案1】:

我建议您保留一些内容以将T 与您的最后一个处理程序相匹配,例如字典。我正在使用static 字典,但如果需要一个实例,(因此它是这种类型和T 的组合,而不仅仅是静态T,不会得到多个处理程序附)改成那个。

为了从事件中删除处理程序,您需要使用-=,并且它需要匹配第一次添加的委托。它equates the delegates 使用创建的对象的实例等。由于您的 lambda(以及从中生成的类/方法)的复杂性,这将很难重新创建,因此以您可以参考的方式存储旧值更容易。

private static Dictionary<Type, NotifyCollectionChangedEventHandler> handlers =
           new Dictionary<Type, NotifyCollectionChangedEventHandler>();
public void SetStorageProviderFor<T>(Expression<Func<T, object>> expr,
                                     IStorageProvider sp) where T : class
{
    var local = Set<T>().Local;
    MemberExpression me = (MemberExpression)expr.Body;

    NotifyCollectionChangedEventHandler existing;
    if (handlers.TryGetValue(typeof(T), out existing))
    {
        local.CollectionChanged -= existing;
    }

    NotifyCollectionChangedEventHandler newHandler =
        (sender, args) =>
        {
            foreach (var item in args.NewItems)
            {
                // get entity's property on member expression and set its value
                // (uses expr and sp)
            }
        };
    local.CollectionChanged += newHandler;
    handlers[typeof(T)] = newHandler;
}

【讨论】:

  • 蒂姆,谢谢。请查看更新后的帖子。我应该发布更多真实的代码...
  • 蒂姆,感谢您为我浪费了这么多时间。将投票并接受答案,但现在我想在我的应用程序中尝试另一种方法(不是因为这个),如果它不成功,那么将使用你的解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-30
  • 1970-01-01
  • 1970-01-01
  • 2014-09-21
  • 2011-07-08
  • 2016-09-08
相关资源
最近更新 更多