How to avoid anonymous methods in "dynamic" event subscription?
How could I refactor the method
private void ListenToPropertyChangedEvent(INotifyProperty开发者_开发百科Changed 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:
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.
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.
精彩评论