Subscribe to Prism EventAggregator events with Reflection
-
13-07-2021 - |
Question
I want to subscribe to an EventAggregator event using Reflection, because I am trying to dynamically wire up event subscriptions between Prism modules at runtime. (I'm using Silverlight 5, Prism and MEF).
What I want to achieve is calling _eventAggregator.GetEvent<MyType>().Subscribe(MyAction)
in one of my modules, but I am stuck at calling _eventAggregator.GetEvent<MyType>()
. How can I proceed from there to call Subscribe(MyAction)
?
Say my Event class is public class TestEvent : CompositePresentationEvent<string> { }
. I don't know this at compile time, but I know the Type at runtime.
Here is what I have got so far:
Type myType = assembly.GetType(typeName); //get the type from string
MethodInfo method = typeof(IEventAggregator).GetMethod("GetEvent");
MethodInfo generic = method.MakeGenericMethod(myType);//get the EventAggregator.GetEvent<myType>() method
generic.Invoke(_eventAggregator, null);//invoke _eventAggregator.GetEvent<myType>();
I would really appreciate a pointer in the right direction.
Solution
You can do this without having to worry about the "type" of event you are invoking by using dynamics.
Type eventType = assembly.GetType(typeName);
MethodInfo method = typeof(IEventAggregator).GetMethod("GetEvent");
MethodInfo generic = method.MakeGenericMethod(eventType);
dynamic subscribeEvent = generic.Invoke(this.eventAggregator, null);
if(subscribeEvent != null)
{
subscribeEvent.Subscribe(new Action<object>(GenericEventHandler));
}
//.... Somewhere else in the class
private void GenericEventHandler(object t)
{
}
Now you really never need to know what the "event type" is.
OTHER TIPS
Could it be as simple as:
var myEvent = generic.Invoke(eventAggregator, null) as CompositePresentationEvent<string>;
if (myEvent != null)
myEvent.Subscribe(MyAction);
Assuming you know the payload type.
Personally, I see the aggregated events that are consumed outside of a module as this module's API and I try to place them in some sort of a shared assembly that other modules can compile against.
I found the answer for the case that the payload type is unknown here:
http://compositewpf.codeplex.com/workitem/6244
Add EventAggregator.GetEvent(Type eventType) to get the event without generic parameters
Build an expression of type Action using reflection
Subscribe to event using reflection (i.e. calling Subscribe method) and passing Expression.Compile as the parameter.
This works if KeepAlive is true.