EventAggregator - Dynamically Creating TEventTypes

Topics: Prism v2 - WPF 3.5
Apr 27, 2009 at 9:13 AM
Hi,

I've created a dynamic search system and i've got a number of different View's to display the results.

I've got a SearchCompletedEvent<T> Composite event and i'd like to dynamically raise the event based on the type rather than calling

if (this.SearchType.Type == typeof(Vehicle)
{
_eventAggregator.GetEvent<SearchCompletedEvent<Vehicle>>().Publish(results);
}
else if (this.SearchType.Type == typeof(Manufacturer)
{
_eventAggregator.GetEvent<SearchCompletedEvent<Manufacturer>>().Publish(results);
}

I'd prefer to do something like 

Type genericType = typeof(SearchCompletedEvent<>).MakeGenericType(this.SearchType.Type);
_eventAggregator.GetEvent<genericType>().Publish(results);

I know the above dosnt work - but hopefully it will illustrate what i'm trying to get to.

Does anyone know how to do this?  Or alternatively have any better solutions for doing something similar?

Any help greatly appreciated!

Thanks,

Andy





Apr 28, 2009 at 8:28 PM

Hi Andy,

 

It might not be the best approach, but there is a way of dynamically creating TEventTypes by reflection. Keep in mind that using reflection might have some performance side effects (especially if you are going to call this method several times).

You will also have to invoke the publish method by reflection, so maybe another approach might be better (in performance, testability, etc).

 

Having said that, the way to dynamically get the event would be as follows:

      Type genericType = typeof(SearchCompletedEvent<>).MakeGenericType(this.SearchType.Type);

      MethodInfo getEventMethod = _eventAggregator.GetType().GetMethod("GetEvent");

      MethodInfo genericGetEventMethod = getEventMethod.MakeGenericMethod(new Type[] { genericType });

object eventToPublish = genericGetEventMethod.Invoke(this._eventAggregator, null);

 

You have the event now, but you won't be able to cast it (things like (SearchCompletedEvent<object>) eventToPublish) won't work) and the base class EventBase has no Publish method, so you will have to invoke Publish() by reflection as well. You can do this as follows:

                MethodInfo publishMethod = eventToPublish.GetType().GetMethod("Publish");

      publishMethod.Invoke(eventToPublish, new object[] { null });

 

Though it's a different approach, you might find the  following solution suitable: you can define a generic abstract class ( for example Searchable<T> in for scenario) that  defines a GetEvent method as follows:

public class Searchable<T>

            {

            public SearchCompletedEvent<T> GetEvent(IEventAggregator _eventAggregator)

            {

                return _eventAggregator.GetEvent<SearchCompletedEvent<T>>();

            }

      }

 

All the classes that you want to publish a SearchCompletedEvent can now inherit from this class. For example:

public class Vehicle : Searchable<Vehicle>

{

      .....

}

 

This way you will enable you to do something like this.SearchType.GetEvent(this._eventAggregator).publish(result) without using reflection. Drawback: you will have to review the class  hierarchy.

 

Hope it helps!

 

Matias Bonaventura

http://blogs.southworks.net/matiasb

Jul 14, 2009 at 10:58 AM

Thanks very much for that Martias, much appreciated!