samedi 3 novembre 2018

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. 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. And it's from 'o' that I want to get the event (specifically, 'CollectionChanged'). But this is what I don't know how to do.

To get 'o', I have used reflection as follows:

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

The first suggestion I tried was 'GetRaisedMethod', which is a property of EventInfo.

So to get the EventInfo, I used the following code:

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:

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."

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.

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 hte item in the collection). None worked for me. Surely it would be simpler, but I've not hit upon a way.





Aucun commentaire:

Enregistrer un commentaire