简体   繁体   English

使用通用参数从反射订阅事件

[英]Subscribe to event from reflection with generic parameters

Alright, so I want to subscribe to an event, using reflection, which has generic parameters. 好吧,所以我想使用反射来订阅一个事件,该事件具有通用参数。

I also want to just make sure I've got the terminology right when I say 'subscribe to an event'. 我还想确保当我说“订阅活动”时,我使用了正确的术语。 I mean something like this: 我的意思是这样的:

Mediator.EventMediator.Instance.PopulateItemsEvent += (sender, args) =>
        {
}

And I want to get ahead of some of you on this one: there are similar questions out there on Stackoverflow and I have read all the ones I could find. 我想在你们中领先一些:Stackoverflow上有类似的问题,我已经阅读了所有可以找到的问题。 Most relate to events without generic parameters or methods with generic parameters. 大多数与没有通用参数的事件或具有通用参数的方法有关。

So, I have a variable called 'o' which is itself a reflected property which is an ObservableCollection. 因此,我有一个名为“ o”的变量,它本身是一个反映的属性,它是一个ObservableCollection。 And it's from 'o' that I want to get the event (specifically, 'CollectionChanged'). 我想从“ o”事件中获取事件(特别是“ CollectionChanged”)。 But this is what I don't know how to do. 但这是我不知道该怎么做。

To get 'o', I have used reflection as follows: 为了得到“ o”,我使用了如下反射:

var o = propertyInfo.GetValue(this, null);

The first suggestion I tried was 'GetRaisedMethod', which is a property of EventInfo. 我尝试的第一个建议是“ GetRaisedMethod”,它是EventInfo的属性。

So to get the EventInfo, I used the following code: 因此,为了获取EventInfo,我使用了以下代码:

EventInfo evi = o.GetType().GetEvent("CollectionChanged", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);

'evi' does seem to contain the correct information, but then if I use this line: 'evi'似乎包含正确的信息,但是如果我使用此行:

var invocation = evi.GetRaiseMethod();

I get null. 我得到空。 But I already read about that in the questions I have already browsed and it seems this is very common. 但是我已经在浏览过的问题中读到了这件事,这似乎很普遍。 Even still, I thought I should try it. 即使如此,我仍然认为应该尝试一下。

Then I went on to another way which was presented in a different question to see if that worked. 然后我继续讨论另一种方法,在另一个问题中提出该方法是否可行。 This is as follows: 如下所示:

var field = typeof(ObservableCollection<>).GetField("CollectionChanged", BindingFlags.NonPublic | BindingFlags.Instance);
var eventDelegate = field.GetValue(o) as MulticastDelegate;

Now this caused an exception for me which I narrowed down to the second of those two lines. 现在这给我造成了一个例外,我缩小到这两行的第二行。 The message was as follows: 消息如下:

"Late bound operations cannot be performed on fields with types for which Type.ContainsGenericParameters is true." “不能对类型为Type.ContainsGenericParameters为true的字段执行后期绑定操作。”

And so this is where I figured this was an event with generic parameters. 因此,这就是我认为这是具有通用参数的事件的地方。 But I've not been able to find anywhere that solves this. 但是我找不到任何可以解决这个问题的地方。 Certainly for a method, you can use MethodInfo.MakeGenericMethod(), but there is no such thing in EventInfo. 当然,对于方法,您可以使用MethodInfo.MakeGenericMethod(),但EventInfo中没有这样的东西。

All I want is to be able to subscribe to that event like normal, but so far it's eluding me. 我想要的是能够像平常一样订阅该事件,但到目前为止,它使我难以理解。

You might also think I can just do something like this: 您可能还认为我可以做这样的事情:

(o as ObservableCollection<>).CollectionChanged +=...

But I can't. 但是我不能。 I've tried all manner of variations of the above (without angular brackets, with, with my own type (of type Type, which is the type of the item in the collection). None worked for me. Surely it would be simpler, but I've not hit upon a way with this approach. 我已经尝试了上述所有形式的变体(没有尖括号,带有我自己的类型(类型为Type,这是集合中项目的类型)。没有一种对我有用。肯定会更简单,但是我还没有找到使用这种方法的方法。

The EventInfo.AddEventHandler method can do the work for you, have a look at this example: EventInfo.AddEventHandler方法可以为您完成工作,请看以下示例:

public static void Main()
{
    var collection = new ObservableCollection<string>(new [] { "a", "b" });
    var o = (object)collection;

    var eventInfo = o.GetType().GetEvent("CollectionChanged");
    var myEventHandler = new Action<object, NotifyCollectionChangedEventArgs>(( s, a ) => Console.WriteLine(a));
    var del = Delegate.CreateDelegate(eventInfo.EventHandlerType, myEventHandler.Method);

    eventInfo.AddEventHandler(o, del);

    collection.Add( "x" );
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM