I have a recurring pattern in my projects.
I have commands which publish eventaggregator-events and I have classes which explicitly subscribe to the events and handle them.
Problem: In the past I have referenced each and every eventhandler from my application root object to ensure that they get created and thus 'live' to be able to catch the event. Is there a way in which I do not have to do this with every event handling class? All the event handlers are named *EventHandler, if that could be of use...
I use Unity for IOC container.
Thanks for any input,
Anders, Denmark
public class PickWishListCommand : BaseCommand, IPickWishListCommand
{
private readonly IEventAggregator _eventAggregator;
public PickWishListCommand(IEventAggregator eventAggregator)
{
_eventAggregator = eventAggregator;
}
public bool CanExecute(object parameter)
{
return true;
}
public void Execute(object parameter)
{
_eventAggregator
.GetEvent<PickWishListEvent>()
.Publish(parameter);
}
}
public class PickWishListEventHandler : IPickWishListEventHandler
{
public PickWishListEventHandler(IEventAggregator eventAggregator)
{
eventAggregator.GetEvent<PickWishListEvent>().Subscribe(OnEvent);
}
private void OnEvent(object obj)
{
throw new System.NotImplementedException();
}
}
public partial class App
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
var container = new UnityContainer();
container
.RegisterTypes(
AllClasses.FromAssembliesInBasePath(),
WithMappings.FromMatchingInterface,
WithName.Default,
WithLifetime.ContainerControlled);
var executionContext = container.Resolve<IExecutionContext>();
var configurationApplicationService = container.Resolve<IConfigurationApplicationService>();
configurationApplicationService.SetupMainWindow();
//Thread.Sleep(3000);
var mainWindow = new MainWindow
{
DataContext = executionContext.MainWindowViewModel
};
mainWindow.Show();
}
}
Edit: I've found a way to auto-instantiate -- but keep the question open; can it be done more elegantly?
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
var container = new UnityContainer();
container
.RegisterTypes(
AllClasses.FromAssembliesInBasePath(),
WithMappings.FromMatchingInterface,
WithName.Default,
WithLifetime.ContainerControlled);
var eventHandlers = new List<object>();
foreach (var registration in container.Registrations)
{
var nameOfRegType = registration.RegisteredType.Name;
var overrides = new ResolverOverride[] { };
if (!nameOfRegType.EndsWith("EventHandler") || !nameOfRegType.StartsWith("I")) continue;
var t = container.Resolve(registration.RegisteredType, overrides);
eventHandlers.Add(t);
}
var executionContext = container.Resolve<IExecutionContext>();
executionContext.EventHandlers = eventHandlers;
var configurationApplicationService = executionContext.ConfigurationApplicationService;
configurationApplicationService.SetupMainWindow();
var mainWindow = new MainWindow
{
DataContext = executionContext.MainWindowViewModel
};
mainWindow.Show();
}
EventHandler
types (classes), to create instances and to do the subscribing job, but I wouldn't recommend that. It's hard to maintain and to test. – dymanoidEventAggregator
I certainly don't have to reference every event handler in application root. The constructors of my various VMs all take a handle toEventAggregator
, using the Unity IoC, and subscribe to any events they are interested in (within their constructor, in my case). Most of those VMs will only be created based on user interaction in the running program. They are then able to respond to events published by various other Vms. – MashtonEventHandler
s classes? Why don't you consume your events in the ViewModels like @Mashton suggests? – dymanoid