Как избежать анонимных методов в "динамической" подписке на события?
Как я мог реорганизовать метод
private void ListenToPropertyChangedEvent(INotifyPropertyChanged source,
string propertyName)
{
source.PropertyChanged += (o, e) =>
{
if (e.PropertyName == propertyName)
MyMagicMethod();
};
}
если бы я хотел избежать использования здесь анонимного метода?
3 ответа
Реализуйте замыкание, которое неявно создается лямбда-выражением явно:
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
}
}
}
Вы можете справиться с этим, имея единый обработчик событий для всех экземпляров, который использует словарь следующих экземпляров:
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
событие в каждом случае.
Я не уверен, чего именно вы пытаетесь достичь или почему вы не хотите использовать анонимные методы, но вы можете сделать что-то более общее:
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 и целевая группа методов могут быть легко заменены. Ваш обработчик событий также строго типизирован, а не анонимен.