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

时间:2011-06-29 06:26:59

标签: c# anonymous-methods

我怎样才能重构方法

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

如果我希望避免在这里使用匿名方法?

3 个答案:

答案 0 :(得分:4)

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

答案 1 :(得分:1)

您可以通过为使用您所关注的实例字典的所有实例提供单个事件处理程序来处理此问题:

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

此版本没有任何错误检查或删除,但它演示了该技术。如果您侦听来自同一来源的多个属性,这一点特别有用。这是因为它只为每个实例的PropertyChanged事件添加了一个处理程序。

答案 2 :(得分:0)

我不确定你想要实现的目标或为什么你不想使用匿名方法,但你可以做更通用的事情:

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

然后你可以像这样使用它:

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

这样你的if测试和目标方法组就可以轻松交换了。您的事件处理程序也是强类型而不是匿名。