这是如何PropertyChanged
通过反射获取事件并触发它的示例。
应该适用于任何类型,甚至适用于基于 Castle 的动态代理。唯一的要求是PropertyChanged
存在。
代码:
使用系统;使用 System.Collections.Generic;使用 System.ComponentModel;使用 System.Reflection;
命名空间 ConsoleApplication1 { 内部类 FooDerived : Foo { }
internal class Foo : INotifyPropertyChanged
{
private string someProperty;
public string SomeProperty
{
get { return someProperty; }
set
{
someProperty = value;
OnPropertyChanged("SomeProperty");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
class Program
{
static void Main(string[] args)
{
var instance = new FooDerived();
instance.PropertyChanged += (sender, e) => Console.WriteLine("Property '{0}' has been changed!", e.PropertyName);
FireEventOn(instance: instance,
eventName: "PropertyChanged",
createEventArgs: () => new PropertyChangedEventArgs(propertyName: "SomeProperty"));
}
// only not null reference to instance is needed
// so will work on any not null instance
// of any type
private static void FireEventOn(object instance, string eventName, Func<object> createEventArgs)
{
BindingFlags flags = BindingFlags.Instance | BindingFlags.NonPublic;
FieldInfo e = GetEvent(eventName, instance.GetType(), lookupWholHierarchy: true);
var eventDelegate = (MulticastDelegate)e.GetValue(instance);
if(eventDelegate == null)
{
// nothing to call
return;
}
foreach (Delegate d in eventDelegate.GetInvocationList())
{
Console.Write("Dynamically firing the event: ");
d.Method.Invoke(d.Target, new[] { instance, createEventArgs() });
}
}
private static FieldInfo GetEvent(string eventName, Type type, bool lookupWholHierarchy = false)
{
if (!lookupWholHierarchy)
{
return type.GetField(eventName, BindingFlags.Instance | BindingFlags.NonPublic);
}
else
{
foreach (var t in GetHierarchy(type))
{
var e = t.GetField(eventName, BindingFlags.Instance | BindingFlags.NonPublic);
if (e != null)
{
return e;
}
}
}
return null;
}
private static IEnumerable<Type> GetHierarchy(Type startFrom)
{
var current = startFrom;
while (current != null)
{
yield return current;
current = current.BaseType;
}
}
}
}
希望这可以帮助。
编辑
更新了代码:添加了(相当愚蠢的)逻辑,用于通过整个继承层次结构查找事件。