取消订阅匿名代表的活动

时间:2012-06-22 08:24:19

标签: c# .net events delegates closures

我想知道如何从事件中取消订阅匿名方法。

我已经检查了Unsubscribe anonymous method in C#,但我的情况略有不同。

我在匿名方法中访问本地函数变量。

代码如下

 private static void Test(Object dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
    {
        if (dependencyPropertyChangedEventArgs.OldValue is ObservableCollection<object>)
        {
            (dependencyPropertyChangedEventArgs.OldValue as ObservableCollection<object>).CollectionChanged -=
                (s, e) => SelectedItemsChanged(dependencyObject, e); // TO FIX event unbsubscription via anonymous delegate
        }

        if (dependencyPropertyChangedEventArgs.NewValue is ObservableCollection<object>)
        {
            (dependencyPropertyChangedEventArgs.NewValue as ObservableCollection<object>).CollectionChanged +=
                (s, e) => SelectedItemsChanged(dependencyObject, e);
        }
    }

2 个答案:

答案 0 :(得分:2)

无法使用匿名代表执行此操作。 为了能够取消订阅,您必须使用通常的代表。

答案 1 :(得分:1)

新答案,现在问题已经改变

基本上,你不能。你的处理程序取决于dependencyObject,它将在每个调用的新对象中捕获,因此你最终会得到不平等的委托。

您可以创建一个新类,其中包含依赖项对象并覆盖Equals以比较这些对象而不是使用匿名函数,或者您可以只保留对先前订阅的引用处理程序。


旧答案,当代表不依赖参数时

奇怪的是,在这种特殊情况下,看起来你没有捕获任何局部变量。所以,可能如果您正在订阅该事件的地点来自此方法,那么您可以放弃:

private static void Test(Object a, DependencyPropertyChangedEventArgs args)
{
    NotifyCollectionChangedEventHandler handler = 
        (s, e) => SelectedItemsChanged(dependencyObject, e);

    var oldObservable = args.OldValue as ObservableCollection<object>;
    if (oldObservable != null)
    {
        oldObservable.CollectionChanged -= handler;
    }
    var newObservable = args.NewValue as ObservableCollection<object>;
    if (newObservable != null)
    {
        newObservable.CollectionChanged += handler;
    }
}

由于您现在只有一个 lambda表达式,我希望将其转换为单个静态方法,因此新创建的委托将等于原始委托。< / p>

但是,我不会推荐。我只是自己创建方法,然后使用方法组转换。