如何通过 Reflection 从基于 Castle 的 DynamicProxy 获取事件处理程序(并调用订阅者,如果
本文关键字:调用 程序 如果 事件处理 获取 Reflection 何通过 DynamicProxy Castle | 更新日期: 2023-09-27 17:56:24
我正在尝试使用 GetField() 以便从实现 INotifyPropertyChanged 的类的基于 Castle 的动态代理访问 EventHandler。然而:
myObject.GetType().GetField( "PropertyChanged", BindingFlags.GetField |BindingFlags.NonPublic |BindingFlags.Instance ) 返回一个 null。
有谁知道通过反射从类的类/动态代理(并调用任何订阅者)访问事件处理程序的任何特殊技巧/方法?
下面是如何通过反射获取事件并触发事件的示例PropertyChanged
。
应该适用于任何类型,甚至适用于基于 Castle 的动态代理。 唯一的要求是PropertyChanged
存在。
法典:
使用系统;使用 System.Collections.Generic;使用系统组件模型;使用系统反射;
命名空间控制台应用程序1{ 内部类 Foo派生 : 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;
}
}
}
}
希望这有帮助。
编辑
更新了代码:添加了(非常愚蠢的)逻辑,用于通过整个继承层次结构查找事件。