I am having trouble with the prism event aggregator. If I subscribe to, and publish an event in the same module it works fine. Like this -
public class InfrastructureModule : IModule
{
private IEventAggregator eventAggregator;
public InfrastructureModule(IEventAggregator eventAggregator)
{
this.eventAggregator = eventAggregator;
eventAggregator.GetEvent<TestEvent>().Subscribe(TestSub);
}
public void Initialize()
{
eventAggregator.GetEvent<TestEvent>().Publish("Infrastructure module");
}
private void TestSub(string s)
{
MessageBox.Show(s);
}
}
However if I subscribe to the event in another module nothing happens when eventAggregator.GetEvent().Publish() is called -
public class OtherModule : IModule
{
private IEventAggregator eventAggregator;
public OtherModule (IEventAggregator eventAggregator)
{
this.eventAggregator = eventAggregator;
}
public void Initialize()
{
eventAggregator.GetEvent<TestEvent>().Publish("Other module");
}
}
The Infrastructure module is registered first so the problem is not that OtherModule is publishing an event before there is a subscriber. Any ideas whats going wrong?
Edit: Here is where I am registering the modules
class Bootstrapper : UnityBootstrapper
{
protected override DependencyObject CreateShell()
{
return new Shell();
}
protected override void InitializeShell()
{
base.InitializeShell();
App.Current.MainWindow = (Window)this.Shell;
App.Current.MainWindow.Show();
}
protected override void ConfigureModuleCatalog()
{
base.ConfigureModuleCatalog();
ModuleCatalog moduleCatalog = (ModuleCatalog)this.ModuleCatalog;
// Infrastructure module
moduleCatalog.AddModule(typeof(Infrastructure.InfrastructureModule));
moduleCatalog.AddModule(typeof(Other.OtherModule));
}
}
Based on the comments of the OP, the objects are instantiated then destroyed right after.
This makes the Publish("OtherModule"); code do nothing, because the listener was destroyed.
Now indeed, if you set KeepSubscriberReferenceAlive to true,
it will work because your EventAggregator will keep a reference to the subscriber object (InfrastructureModule).
That is not ideal, basically you went from using a Weak Event Pattern where you don't risk memory leaks, to having to handle objects lifetime and thus risk memory leaks just like a regular .NET event.
Don't get me wrong, I'm not saying you absolutely shouldn't use KeepSubscriberReferenceAlive, but it should only be used on rare occasions.
That being said, your test case is an odd scenario: the Bootstrapper will call Initialize on every Module you define, and then your shell does not hold those modules. Since nobody holds those Modules, they're destroyed.
The "normal" usage for Initialize, is to inject the module that is being initialized into the Shell (or any other UserControl), and it makes sense: you don't want to initialize something you will not use.
Related
I have a WCF service that uses Simple Injector for dependency injection. I want to wire up some event handlers in the container bootstrapper. I have created an interface IStatusChangeNotification:
public interface IStatusChangeNotification
{
event EventHandler<int> JobStatusChange;
}
My CommandHandler implements IStatusChangeNotification and there are two event handler classes EmailNotification and MmrNotification, each defining a Notify() method. Then in my bootstrap code I have the following:
container.Register<EmailNotification>();
container.Register<MmrNotification>();
container.RegisterManyForOpenGeneric(typeof(ICommandHandler<>),
Assembly.GetExecutingAssembly());
container.RegisterInitializer<IStatusChangeNotification>(scn =>
{
scn.JobStatusChange += container.GetInstance<EmailNotification>().Notify;
scn.JobStatusChange += container.GetInstance<MmrNotification>().Notify;
});
This works and the notifications are received. My question is whether this is the correct/best approach for wiring up event handlers? How do I remove the handlers at the end of the request and will failing to remove them result in a memory leak?
Although your approach might work, I think this part of your system design might deserve the same amount of attention as your command handlers do. The most common reason for command handlers to trigger events, is to publishing events that describe some business related action. So instead of using .NET events, model those domain events the same way as you model your commands:
// Abstractions
public interface IEventHandler<TEvent> where TEvent : IDomainEvent {
void Handle(TEvent e);
}
public interface IEventPublisher {
void Publish<TEvent>(TEvent e) where TEvent : IDomainEvent;
}
// Events
public class JobStatusChanged : IDomainEvent {
public readonly int JobId;
public JobStatusChanged(int jobId) {
this.JobId = jobId;
}
}
// Container-specific Event Publisher implementation
public class SimpleInjectorEventPublisher : IEventPublisher {
private readonly Container container;
public SimpleInjectorEventPublisher(Container container) {
this.container = container;
}
public void Publish<TEvent>(TEvent e) {
var handlers = container.GetAllInstances<IEventHandler<TEvent>>();
foreach (var handler in handlers) {
hanlder.Handle(e);
}
}
}
With the previous infrastructure, you can create the following event and command handlers:
// Event Handlers
public class EmailNotificationJobStatusChangedHandler
: IEventHandler<JobStatusChanged> {
public void Handle(JobStatusChanged e) {
// TODO: Implementation
}
}
public class MmrNotificationJobStatusChangedHandler
: IEventHandler<JobStatusChanged> {
public void Handle(JobStatusChanged e) {
// TODO: Implementation
}
}
// Command Handler that publishes
public class ChangeJobStatusCommandHandler : ICommandHandler<ChangeJobStatus> {
private readonly IEventPublisher publisher;
public ChangeJobStatusCommandHandler(IEventPublisher publisher) {
this.publisher = publisher;
}
public void Handle(ChangeJobStatus command) {
// change job status
this.publisher.Publish(new JobStatusChanged(command.JobId));
}
}
Now you can register your command handlers and event handlers as follows:
container.RegisterManyForOpenGeneric(typeof(ICommandHandler<>),
Assembly.GetExecutingAssembly());
// This registers a collection of eventhandlers with RegisterAll,
// since there can be multiple implementations for the same event.
container.RegisterManyForOpenGeneric(typeof(IEventHandler<>),
container.RegisterAll,
Assembly.GetExecutingAssembly());
This removes the need to register each event handler class seperately, since they are simply implementations of IEventHandler<JobStatusChanged> and can all be batch-registered in one line of code. There's also no need to use RegisterInitializer to hook any events using custom defined interfaces.
Other advantages of this are:
The dependency between a command handler and the IEventPublisher interface makes it very clear that this command is publishing events.
The design is much more scalable, since its less likely for the composition root to have to change when new commands and events are added to the system.
It does your domain much good, since each event gets its own entity in the system.
It will be much easier to change the way events are processed, since that's now an implementation detail of the SimpleInjectorEventProcessor. For instance, you can deside to run them in parallel, run them in their own transaction, process them later (by storing them in an event store).
Apologise if this a really stupid question but I'm just getting started with caliburn.micro and I'm struggling with getting the eventAggregator, nothing seems to be subscribing...
I'm not sure whether the problem is with the view model or the bootstrapper. Here is the viewmodel:
class MainWindowViewModel : Screen
{
private readonly IEventAggregator _eventAggregator;
public MainWindowViewModel(IEventAggregator eventAggregator)
{
_eventAggregator = eventAggregator;
_eventAggregator.Subscribe(this);
}
public void SayHello()
{
_eventAggregator.Publish("Hello World!");
}
public void Handle(string message)
{
MessageBox.Show(message);
}
}
Bootstrapper:
class AppBootstrapper : Bootstrapper<MainWindowViewModel>
{
public static readonly Container ContainerInstance = new Container();
protected override void Configure()
{
ContainerInstance.Register<IWindowManager, WindowManager>();
ContainerInstance.RegisterSingle<IEventAggregator,EventAggregator>();
ContainerInstance.Register<MainWindowViewModel, MainWindowViewModel>();
ContainerInstance.Verify();
}
protected override IEnumerable<object> GetAllInstances(Type service)
{
return ContainerInstance.GetAllInstances(service);
}
protected override object GetInstance(System.Type service, string key)
{
return ContainerInstance.GetInstance(service);
}
protected override void BuildUp(object instance)
{
ContainerInstance.InjectProperties(instance);
}
}
Any ideas what I'm missing, I feel I must not be linking somewhere...
I am using SimpleInjector as the IOC Container
EDIT:
It seems like a very simple case of I didn't know what I was doing. RTFM.
Implementing IHandle does work. It seems to get called twice the first time the type is handled though. I'll do some investigating as to why.
It sounds like you've already arrived at a solution of sorts.
I believe it should work provided you implement an IHandle<T> interface using a type compatible with the even you're publishing. E.g:
class MainWindowViewModel : Screen, IHandle<string>
{
//... Your Code
public void Handle(string myEventstring)
{
// Do Something.
}
}
If at all helpful, when I use the EventAggregator, I tend to create a static EventAggregator instance (from a small helper class) which I use in any ViewModels that require it - it may help in cases where you've actually initialised the EventAggregator multiple times by accident (might be the cause of your double event).
I also sometimes create small helper classes to wrap up event information. E.g:
public sealed class DownloadFinishedEvent
{
public readonly string EventText = "Download Completed";
// Additional Download Info Here.
public override string ToString()
{
return this.EventText;
}
}
The caliburn micro doc example shows, that the subscriber has to implement the IHandle interface. I think that's the problem.
in a service class I have a method at which end I want to raise an event that can be listened by other two services.
This is how I'm trying to do it. But my problem is that the null check for the handler is always true.
Inside the IProfileService file I define the delegate and the actual interface
public delegate void PersonDetailsUpdated(Person person, bool personDetailsWereUpdated);
public interface IProfileService
{
void UpdateContactDetails(Person person);
event PersonDetailsUpdated PersonDetailsUpdatedEvent;
}
And this is the instance of that interface
public class ProfileService : IProfileService
{
// ... Dealing with dependency injection
public event PersonDetailsUpdated PersonDetailsUpdatedEvent;
public void UpdateContactDetails(Person person)
{
//... Doing stuff
//We raise an event
var handler = PersonDetailsUpdatedEvent;
if (handler != null)
{
handler(person, personDetailsWereUpdated);
}
}
}
}
Now in the other two services I do this (I only put the code of one of them)
internal class CustomerSmsService : ICustomerSmsService
{
private readonly IPersonDAL _personDal;
// ... Other dependencies...
public CustomerSmsService(IPersonDAL personDal, /* ... the other dependencies */ IProfileService profileService)
{
_personDal = personDal;
//... Again the other dependencies
profileService.PersonDetailsUpdatedEvent += (SendPhoneValidationCode);
}
//... Other methods
// What I understand is the so called Listener
public void SendPhoneValidationCode(Person person, bool personDetailsWereUpdated)
{
//Stuff
}
}
Maybe the answer is obvious but haven't worked with events before and I'm finding it impossible to figure out or to find an example that is clear enough for me although there's quite a bunch of them. But they seem to have followed another approach.
Thanks
I have two .NET parties who needs be bound by a contract. Now, party1 and party2 need to be able call some methods on each other (most of it is calls and reporting result back). I have duplex contract in mind, but the parties are not using WCF.
Is there a design pattern for this?
Edit
The parties are part of the same application. I create the application (party1) and someone else creates a dll (party2) that I load dynamically. Now, both of us should be able to call methods on each other. So, I am out to create an interface contract between us. The intent is to know whether there is a know pattern to do that?
A common solution is to use some kind of pub/sub pattern. By doing so you can avoid circular dependencies.
Basically you create some kind of class which are used to subscribe on events (and publish them).
So both your classes does something like this (but with different events):
public class ClassA : IEventHandler<UserCreated>
{
IEventManager _eventManager
public ClassA(IEventManager manager)
{
// I subscribe on this event (which is published by the other class)
manager.Subscribe<UserCreated>(this);
_eventManager = manager;
}
public void Handle(UserCreated theEvent)
{
//gets invoked when the event is published by the other class
}
private void SomeInternalMethod()
{
//some business logic
//and I publish this event
_eventManager.Publish(new EmailSent(someFields));
}
}
The event manager (simplified and not thread safe):
public class EventManager
{
List<Subscriber> _subscribers = new List<Subscriber>();
public void Subscribe<T>(IEventHandler<T> subscriber)
{
_subscribers.Add(new Subscriber{ EventType = typeof(T), Subscriber = subscriber});
}
public void Publish<T>(T theEvent)
{
foreach (var wrapper in subscribers.Where(x => x == typeof(theEvent)))
{
((IEventHandler<T>)wrapper.Subscriber).Handle(theEvent);
}
}
}
The small wrapper:
public class Subscriber
{
public Type EventType;
public object Subscriber;
}
Voila. the two classes are now loosely coupled from each other (while still being able to communicate with each other)
If you use an inversion of control container it get's easier since you can simplify the event manager and just use the container (service location) to resolve all subscribers:
public class EventManager
{
IYourContainer _container;
public EventManager(IYourContainer container)
{
_container = container;
}
public void Publish<T>(T theEvent)
{
foreach (var subscriber in _container.ResolveAll<IEventHandler<T>>())
{
subscriber.Handle(theEvent);
}
}
}
I think you can use next logic:
Class1: Interface1 , Class2:Interface2,
class Manager{
public Manager(Interface1 managedPart1,Interface2 managedPart2){
... some logic for connect to interfaces
}
}
This way reminds me pattern Bridge, but this is very subjective
In my product I need process wide events. For that I used code like this:
public class Global
{
public static event EventHandler<MyEventArgs> Message;
public static void ShowMessage();
}
Now let's say I have a WinForms user interface. In form's code I will subscribe to this event and handle it in some default way (eg. by using System.Windows.Forms.MessageBox.Show() method). Now the question is how do I allow user to create derived form and override my default Message event handler implementation?
Just subscribing to the event for the second time with custom implementation doesn't solve the problem (both event handlers would be executed and potentially two message boxes shown). The options I see are either:
//call OnSubscribeToMessageEvent() from either form's constructor or OnLoad event handler
protected virtual void OnSubscribeToMessageEvent()
{
Global.Message += new EventHandler<MyEventArgs>(Global_Message);
}
private void Global_Message(object sender, MyEventArgs e)
{
//my default implementation
}
or
//subscribe in either form's constructor or OnLoad event handler
protected virtual void Global_Message(object sender, MyEventArgs e)
{
//my default implementation
}
Which version is better and why? Or maybe there are any other options?
I still have some doubts as I have never seen such a design pattern in any .NET library
Yes, you're right to worry about this. These kind of event subscriptions are very fickle, the event source always outlives the subscriber. There's only one class in the framework I know that does this, SystemEvents. The problem is that every subscriber has to very carefully unsubscribe itself when its lifetime ends or the object will stay referenced forever. A memory leak that's very hard to diagnose.
A better pattern here is to use an interface. Let's declare one:
public class MyEventArgs { /* etc.. */ }
public interface IGlobalNotification {
event EventHandler Disposed;
void OnMessage(MyEventArgs arg);
}
Now you can have a form implement the interface:
public partial class Form1 : Form, IGlobalNotification {
public Form1() {
InitializeComponent();
GlobalMessages.Register(this);
}
void IGlobalNotification.OnMessage(MyEventArgs arg) {
// do something
}
}
The Register method registers the form with the GlobalMessages class, the Dispose event ensures that the class can detect that the form is dying:
public static class GlobalMessages {
public static void Register(IGlobalNotification listener) {
listener.Disposed += delegate { listeners.Remove(listener); };
listeners.Add(listener);
}
public static void Notify(MyEventArgs arg) {
foreach (var listener in listeners) listener.OnMessage(arg);
}
private static List<IGlobalNotification> listeners = new List<IGlobalNotification>();
}
Call GlobalMessages.Notify() to get the OnMessage() method to run in all live form instances. The major advantage of this approach is that a client programmer can never screw up.
I would let the derived class override the Global_Message. The subscription to the event is generic and why would you want to implement it in every child again? It also gives you the option to call base.Global_Message(sender, e) in case your child class just wants to add some decoration to it and use the default behaviour otherwise.
I would prefer your second example, as that way, classes that extend your base class only have to override one method and do not have to remove the handler added by the base class from the event.
The key is adding the virtual keyword, so that a derived type can overide the method and the method they created will be called instead.
//subscribe in either form's constructor or OnLoad event handler
protected virtual void Global_Message(object sender, MyEventArgs e)
{
//my default implementation
}
Now that you've added virtual to both, I'd go with the first and override the one that subscribes to the event, if they didn't want the event subscribed to.
Though there is another option, call it #3.
protected EventHandler GlobalMessageEvent = new EventHandler<MyEventArgs>(Global_Message);
protected virtual void OnSubscribeToMessageEvent()
{
// this could be done in the Form_Load() or constructor instead.
Global.Message += GlobalMessageEvent;
}
Then potentially an inherited class could do somewhere: (note the -=)
{
Global.Message -= GlobalMessageEvent;
}