简体   繁体   English

如何避免“动态”事件订阅中的匿名方法?

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

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?如果我想避免在这里使用匿名方法?

Implement the closure that is implicitly created by the lambda explicitly:实现由 lambda 显式创建的闭包:

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

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.这是因为它只为每个实例的PropertyChanged事件添加一个处理程序。

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.这样你的 if 测试和目标方法组可以很容易地交换。 Your event handler is also strongly typed rather than anonymous.您的事件处理程序也是强类型而不是匿名的。

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

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