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<object, NotifyCollectionChangedEventArgs> act = (sender, args) => { }

but CollectionChanged cannot accept this Action as handler :( Any help is appreciated. 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. 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 ;(

Answers


I'd recommend that you keep something to match T to your last handler, such as a dictionary. 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.

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.

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;
}

Need Your Help

Preventing Unauthorized CMS Access

c# asp.net security hacking

Recently someone tried attempting a brute force password hack of my CMS. I know this because the max attempts before a password gets locked has been reached.

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.