How to avoid anonymous methods in “dynamic” event subscription?

天涯浪子 提交于 2019-12-12 10:47:16

问题


How could I refactor the method

private void ListenToPropertyChangedEvent(INotifyPropertyChanged source,
                                          string propertyName)
{
    source.PropertyChanged += (o, e) =>
    {
        if (e.PropertyName == propertyName)
            MyMagicMethod();
    };
}

if I wished to avoid using the anonymous method here?


回答1:


Implement the closure that is implicitly created by the lambda explicitly:

private void ListenToPropertyChangedEvent(INotifyPropertyChanged source,
                                          string propertyName)
{
    var listener = new MyPropertyChangedListener(propertyName);
    source.PropertyChanged += listener.Handle;
}

class MyPropertyChangedListener
{
    private readonly string propertyName;

    public MyPropertyChangedListener(string propertyName)
    {
        this.propertyName = propertyName;
    }

    public void Handle(object sender, PropertyChangedEventArgs e)
    {
        if (e.PropertyName == this.propertyName)
        {
            // do something
        }
    }
}



回答2:


You can handle this by having a single event handler for all instances that uses a dictionary of instances that you are following:

private Dictionary<INotifyPropertyChanged, List<string>> sourceMap =
    new Dictionary<INotifyPropertyChanged, List<string>>();

private void ListenToPropertyChangedEvent(INotifyPropertyChanged source,
                                            string propertyName)
{
    if (sourceMap.ContainsKey(source))
        sourceMap[source].Add(propertyName);
    else
    {
        source.PropertyChanged += source_PropertyChanged;
        sourceMap[source] = new List<string> { propertyName };
    }
}

void source_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
    var source = sender as INotifyPropertyChanged;
    var list = sourceMap[source];
    if (list.Contains(e.PropertyName))
        MyMagicMethod();
}

This version doesn't have any error checking or removal but it demonstrates the technique. It is particularly valuable if you listen for multiple properties from the same source. This is because it only adds a single handler to the PropertyChanged event per instance.




回答3:


I'm not sure exactly what youre trying to achieve or why you dont want to use anonymous methods, but you could do something more generic:

    private PropertyChangedEventHandler GetHandler
      (Func<PropertyChangedEventArgs, bool> test, Action toInvoke)
    {
        return new PropertyChangedEventHandler(
            (o, e) => 
            {
               if (test(e))
                toInvoke(); 
            }); 
    }

Then you can use it like so:

  source.PropertyChanged += GetHandler                
            (
                p => p.PropertyName == propertyName, MyMagicMethod
            ); 

That way your if test and the target method group can be swapped about easily. Your event handler is also strongly typed rather than anonymous.



来源:https://stackoverflow.com/questions/6516528/how-to-avoid-anonymous-methods-in-dynamic-event-subscription

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!