I am trying to refactor some of my methods in the PRISM framework, and it's not really working out.
I need to publish messages through the EventAggregator
, and I have written a reflection method which will look through a List<Parameters>
containing Type
s and from here send the messages.
But it never sends any messages.
It turns out the safecast as PubSubEvent<object>
is not the same as public class Input: PubSubEvent<Output> {}
, which means the returnObj?.Publish(data);
is null
and will not be called.
public struct Parameters
{
public string Topic;
public Type Input;
public Type Output;
}
private List<Parameters> _list;
...
void SomeFunction()
{
_list.ForEach(m =>
{
var data = JsonConvert.DeserializeObject(dataString, m.Output);
var eventAggType = _eventAggregator.GetType();
var eventMethod = eventAggType.GetMethod("GetEvent");
var genericMethod = eventMethod.MakeGenericMethod(m.Input);
var returnObj = genericMethod.Invoke(_eventAggregator, null) as PubSubEvent<object>;
returnObj?.Publish(data);
// var datType = returnObj.GetType();
// if (datType.BaseType.Name == typeof (PubSubEvent<object>).Name)
// {
// var obj = Convert.ChangeType(returnObj, datType);
// ((PubSubEvent<object>) obj).Publish(data);
// }
}
}
I tried to modify the code by looking at the type it actually outputs (remove the as PubSubEvent<object>
), and it's the same BaseType
.
But the casting to a basic PubSubEvent
is not something the program is happy about.
Exception thrown: 'System.InvalidCastException' in MyProject.ModuleA.dll
EXCEPTION: Unable to cast object of type 'MyProject.ModuleA.GlobalEvents.EventA' to type 'Microsoft.Practices.Prism.PubSubEvents.PubSubEvent`1[System.Object]'.
How do I Publish
with the correct type?
It should look like the following, if you knew what classes you were handling:
_eventAggregator.GetEvent<EventA>().Publish(data);
Silly me. It's reflection - with more reflection!
void SomeFunction()
{
_list.ForEach(m =>
{
//Deserialize the data
var data = JsonConvert.DeserializeObject(dataString, m.Output);
//Obtain the object from the EventAggregator
var eventAggType = _eventAggregator.GetType();
var eventMethod = eventAggType.GetMethod("GetEvent");
var genericMethod = eventMethod.MakeGenericMethod(m.Input);
var returnObj = genericMethod.Invoke(_eventAggregator, null);
//Publish the data
var publishMethod = returnObj.GetType().GetMethod("Publish");
publishMethod.Invoke(returnObj, new[] {data});
});
}
So you take the reflection, returnObj
, and reflect the function Publish(...)
and Invoke
it from your reflected object, returnObj
, with the data
parameter.