0

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

LINQ2Vodka
  • 2,996
  • 2
  • 27
  • 47
  • 1
    [1](http://stackoverflow.com/questions/937181/c-sharp-pattern-to-prevent-an-event-handler-hooked-twice), [2.a](http://stackoverflow.com/questions/1486214/c-sharp-removing-an-event-handler), [2.b](http://stackoverflow.com/questions/1307607/removing-event-handlers?lq=1) – Yosi Dahari Nov 20 '13 at 17:31
  • You may want to try this `CollectionChangedEventHandler act = (sender, args) => { };` instead. – King King Nov 20 '13 at 17:33
  • @KingKing just tried `Set().Local.CollectionChanged += (NotifyCollectionChangedEventHandler)act`, it says unable to cast – LINQ2Vodka Nov 20 '13 at 17:34
  • @KingKing "Delegate CollectionChangedEventHandler doesn't have type parameters" – LINQ2Vodka Nov 20 '13 at 17:35
  • @jim so what's the type of `Local`? – King King Nov 20 '13 at 17:37
  • @KingKing Local is `System.CollectionObjectModel.ObservableCollection`, and `Set' is Entity Framework entities set. – LINQ2Vodka Nov 20 '13 at 17:51
  • @jim What defines which previously-attached handlers should be removed, e.g. do you want to remove a previously-added handlers with the same `T`, or only with the same `T`, `expr`, and `sp`? – Tim S. Nov 20 '13 at 18:35

1 Answers1

2

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;
}
Tim S.
  • 55,448
  • 7
  • 96
  • 122
  • Tim, thank you. Please, take a look at updated post. I should have posted more real code... – LINQ2Vodka Nov 20 '13 at 18:15
  • Tim, thanks for wasting so much time for me. Will upvote and accept the answer, but now i wanna try totally another approach in my app (not because of this), and if it's unsuccessful, then will use your solution. – LINQ2Vodka Nov 20 '13 at 19:18