添加到委托的附加信息

Additional information added to a delegate

也许这个问题已经被问过很多次,也已经解决了很多次,但我可能用错了术语,因为到目前为止我还没有想出答案。

所以我有一个 ObservableCollection,我使用反射来调用 'CollectionChanged' 事件处理程序。

它看起来像这样('o' 是有问题的 ObservableCollection,也是通过反射获得的):

                EventInfo evi = o.GetType().GetEvent("CollectionChanged", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
                var eventHandler = new Action<object, NotifyCollectionChangedEventArgs>(
                    (s, a) => 
                    {
                        // Event code here
                    });

                 var del = Delegate.CreateDelegate(evi.EventHandlerType, eventHandler.Method);

                 evi.AddEventHandler(o, del);

此操作的调用是自动的,并且在 属性 'o' 的元素发生更改时调用。我可以调用消息框等,但我希望在此操作中捕获某种信息。特别是,这一切所在的 class 有一个 ID,它是一个简单的 int。我想捕获这个 int 并在动作中使用它。由于它的自动化特性,我似乎无法添加任何其他参数,所以我不确定如何管理它。

编辑:

我想我要做的是创建一个新项目并尝试找出我遇到的问题。只是为了弄清楚这在哪里结束,我尝试简单地在声明事件的 class 中存在的事件中引用 属性,我得到了 'cannot bind to the target method because its signature or security transparency is not compatible with that of the delegate type' 异常。我还会看到问题吗?这就是我想知道的。

代码在这里:Code

这很简单,只是一个测试 class。所有其余代码(MainWindow.xaml.cs 因为它是 WPF 项目)是创建 TestClass 的实例,将 TestInt 设置为 10001,然后在该实例上调用 TestMethod。

事件中没有 'this.TestInt',它工作正常。有了它,异常依旧。

由于 lambda 捕获会导致创建状态对象,因此在从旧委托创建新委托时必须考虑 Target。所以你需要使用下面的 CreateDelegate(Type, Object, MethodInfo) 重载。即使对于没有目标对象的委托,此方法也是安全的,msdn 告诉我们有关对象参数的信息:

The object to which the delegate is bound, or null to treat method as static (Shared in Visual Basic).

您的代码的以下改编应该可以完成这项工作:

var o = p.GetValue(this,null);
EventInfo eventInfo = t.GetEvent("CollectionChanged", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);

var handler = new Action<object, NotifyCollectionChangedEventArgs>((s, a) => { Console.WriteLine("Changed + " + this.TestInt.ToString()); });

Delegate del = Delegate.CreateDelegate(eventInfo.EventHandlerType, handler.Target, handler.Method);

eventInfo.AddEventHandler(o, del);