如何通过 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。

有谁知道通过反射从类的类/动态代理(并调用任何订阅者)访问事件处理程序的任何特殊技巧/方法?

如何通过 Reflection 从基于 Castle 的 DynamicProxy 获取事件处理程序(并调用订阅者,如果

下面是如何通过反射获取事件并触发事件的示例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;
        }
    }

   }
}

希望这有帮助。

编辑
更新了代码:添加了(非常愚蠢的)逻辑,用于通过整个继承层次结构查找事件。