简体   繁体   English

如果事件处理程序不存在,如何恰好添加一次

[英]How to add an event handler exactly once, if it doesn't exists

I need to add and remove event handlers on my collection change: 我需要在我的集合更改中添加和删除事件处理程序:

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. How do i prevent adding the same handler? 如何防止添加相同的处理程序?
  2. How can i remove some specific handler? 我该如何删除一些特定的处理程序? I don't think I should repeat all the same code but with "-=" mark... 我不认为我应该重复所有相同的代码,但用“ - =”标记...
    I also tried to make the handler an Action to store it in memory and let it be unassigned from CollectionChanged at any time: 我还试图让处理程序成为一个Action来将它存储在内存中,并让它随时从CollectionChanged中取消分配:

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

but CollectionChanged cannot accept this Action as handler :( CollectionChanged无法接受此Action作为处理程序:(
Any help is appreciated. 任何帮助表示赞赏。
UPDATE UPDATE
My apologies, i shoud have posted more real code. 我道歉,我发布了更多真实的代码。 The problem is that my handler is using more parameters than only of CollectionChanged and needs also expr and sp of the SetStorageProviderFor method. 问题是我的处理程序使用的参数多于CollectionChanged参数,还需要SetStorageProviderFor方法的exprsp In this case I can create named method as Tim S. advices but if i provide it with additional params then i'll not be able to assign it to Set<T>().Local.CollectionChanged directly, will need anonymous lambda again ;( 在这种情况下,我可以创建命名方法作为Tim S.建议,但如果我提供额外的参数,那么我将无法将其分配给Set<T>().Local.CollectionChanged直接,将需要匿名lambda; (

I'd recommend that you keep something to match T to your last handler, such as a dictionary. 我建议您保留一些东西以匹配T到您的上一个处理程序,例如字典。 I'm using a static dictionary, but if an instance one is what's needed, (so that it's the combination of this type and T , and not just statically T , that won't get more than one handler attached) change it to that. 我正在使用一个static字典,但如果一个实例是需要的,(因此它是这种类型和T的组合,而不仅仅是静态T ,它不会得到多个处理程序)将它改为。

In order to remove a handler from an event, you need to use -= and it needs to match the delegate that was first added. 为了从事件中删除处理程序,您需要使用-=并且它需要匹配首次添加的委托。 It equates the delegates using, among other things, the instance of the object that is created. 等同于代理使用创建的对象的实例等。 This would be difficult to recreate due to the complexity of your lambda (and the classes/methods that are generated from it), so it's easier to store the old value in a way you can refer back to. 由于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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM