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
Related
I'm using a series of Template Pattern classes that represent different types of events.
internal abstract class DayEndingEvent : Event
{
internal void OnDayEnding(object? sender, DayEndingEventArgs e)
{
if (IsHooked) OnDayEndingImpl(sender, e);
}
protected abstract void OnDayEndingImpl(object? sender, DayEndingEventArgs e);
}
This pattern ensures that the implementation only runs if the event is "hooked", which allows other parts of the application to activate/deactivate the event by calling Hook and Unhook methods from the base Event class.
internal abstract class Event
{
public bool IsHooked {get; private set;}
public bool Hook() => !IsHooked && (IsHooked = true);
public bool Unhook() => IsHooked && !(IsHooked = false);
}
(Event is obviously more complex than this, but this is enough to get the picture).
My EventManager can instantiate one of every implementation of this pattern and hook their OnDayEnding to the appropriate handler in an external API.
This has worked fine for a while, but now I have a new requirement to add prioritization to these classes. The only way to do so (and this is a limitation of the external API) is by adding attribute [EventPriority] to the event callback. But obviously I can't annotate OnDayEnding with a priority since that would set the priority of all implementations, which defeats the whole purpose.
The attribute will have no effect anywhere else but on the callback. The only other solution I can see is to remove the Impl and just make the callback itself abstract. But that means I'd have to manually check the IsHooked flag on every implementation, which is what I want to avoid.
So question is, can anybody sugest an alternative to this pattern that would both 1) allow me to have different implementations of the callback, to which I can add priority attributes, and 2) enforce the check for IsHooked?
There are two possibilities I have come across recently when I encountered a similar problem:
Option one, have an entry method that has the required attributes:
public class SpecificImplementationClass1 : BaseClass, IInitializer
{
[SomeAttribute]
public void CallMeToInitiate(SomeType input)
{
ExecuteCommonCode(input);
}
protected override void ExecuteSpecificCode(object input)
{
var typedInput = (SomeType) input;
// ...execute whatever implementation-specific code here
}
}
public class BaseClass
{
protected void ExecuteCommonCode(object input)
{
// DoSomethingBefore(input);
ExecuteSpecificCode(input);
// DoSomethingAfter(input);
}
protected abstract void ExecuteSpecificCode(object input);
}
public interface IInitializer
{
void CallMeToInitialize(SomeType input);
}
// Get all IInitializers through dependency injection and call "CallMeToInitialize(new SomeType())" on each
Option two, use the template delegate pattern
I have created a test project as a POC for this problem.
I have a WPF app, that when we use interceptors around the view models, it's stopping the propagation of events. If I disable all interceptors, it works fine.
Here is the code:
MyInterceptor.cs
public class MyInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
invocation.Proceed();
}
}
IoCTestViewModel.cs
public interface IIoCTestViewModel : INotifyPropertyChanged
{
int Number { get; }
}
public class IoCTestViewModel : IIoCTestViewModel
{
public IoCTestViewModel()
{
var timer = new Timer(200);
timer.Elapsed += (a, b) => {
if(PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("Number"));
}
};
timer.Start();
}
public int Number
{
get
{
return new Random().Next(1, 100);
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
IoCTest.xaml.cs
public partial class IoCTest : UserControl
{
public IIoCTestViewModel ViewModel { get; set; }
public IoCTest(IIoCTestViewModel viewModel)
{
InitializeComponent();
DataContext = viewModel;
}
}
App.xaml (fragment)
Container = new WindsorContainer();
Container.Register(Component.For<MyInterceptor>().ImplementedBy<MyInterceptor>());
Container.Register(Component.For<IIoCTestViewModel>().ImplementedBy<IoCTestViewModel>().Interceptors<MyInterceptor>());
Container.Register(Component.For<IoCPage>().ImplementedBy<IoCTest>()); //IoCTest is a usercontrol
OK. So once I get an instance of IoCTest and add it to a page, I don't see any changes, even though I am sending PropertyChanged every 200ms. If I remove the interceptor, everything works fine.
So how do I fix this?
The issue here is that because you declare your service to be IIoCTestViewModel, when you add an interceptor Windsor simply creates a dynamic proxy that delegates all calls to your implementation type. However, the interception is done using composition - one object delegating to another. Hence, when you raise your property changed event with a sender of this, it is a different object to the one that WPF thinks it is watching.
You should instead register your view model like this:
Container.Register(Component.For<IIoCTestViewModel,IoCTestViewModel>().ImplementedBy<IoCTestViewModel>().Interceptors<MyInterceptor>())
By specifying multiple services, one of which is actually your implementation class, Windsor will instead generate a class proxy - i.e. the interception will be done using inheritance, with the generated proxy inheriting from IoCTestViewModel. (This is known as type forwarding in Windsor). Now when you raise your event with a sender of this it correctly refers to the same instance that WPF is watching.
See here for a more detailed explanation of type forwarding and its implications for proxies
I do not understand some things of work with callbacks.
I have some third-party code wich connect,disconnect,subscribe to values from some system.
So, the example is:
class Subscriber:ISubscriber
{
public void OnConnected()
{
}
public void OnDisconnected()
{
}
}
Then, it uses:
var subscriber=new Subscriber();
_someSystemObj.CreateConnection(subscriber); //i do not understand how it works there
And then _someSystemObj calls OnConnected or OnDisconnected.
So, i have two questions:
1.How can _someSystemObj calls OnConnected method (it use Observer pattern or may be it use it other way. Can you describe it? Get some schematic code to understand how it may work.
If i want to do many steps when OnDisconnect happens: should i throw some public event to other classes? I mean than i can not do Disconnection in this OnDisconnect method (i have to do some steps in other part of my code and at old version of this API i just rethrow event OnDisconnect on top of my program and then handle it.)
This old version of code looks like:
_server.OnDisconnect+=OnDisconnectHandler;
void OnDisconnectHandler(..)
{
if(OnReconnect!=null)//some public event
OnReconnect(e);// throw on top of my program and then handle it there
}
At new version of API i try to solve it by add public event and when OnDisconnect happens throw it on top:
class Subscriber:ISubscriber
{
public event EventHandler<EventArgs> OnDisconnectedHappens;
public void OnConnected()
{
}
public void OnDisconnected()
{
if(OnDisconnectedHappens!=null)
OnDisconnectedHappens(this,e);//thow on top
}
}
And in some place:
_subscriber.OnDisconnectHappens+=OnDisconnectHandler; //and do my work
Or, may be it not right way. May be i should do something else?
Please,can you give me a some link, that i can learn about this model of event callbacks?
Or, may be i do it correctly?
How can _someSystemObj call OnConnected method?
Well, you gave it a subscriber when you called CreateConnection(subscriber). It's probably implemented something like this:
private readonly List<ISubscriber> _subscribers = new List<ISubscriber>();
public void CreateConnection(ISubscriber subscriber)
{
_subscribers.Add(subscriber);
}
private void OnConnectedNotifySubscribers()
{
foreach (ISubscriber subscriber in _subscribers)
{
subscriber.OnConnected();
}
}
If I want to do many steps when OnDisconnect happens, should I raise some public event to other classes?
That is a valid option, but it can get difficult to debug when there are too many layers in an event chain. Another option is to increase the capability of your Subscriber class so that it can do everything necessary to handle the subscription events.
class EmpoweredSubscriber : ISubscriber
{
private readonly DisconnectWorker _worker;
private readonly DisconnectHelper _helper;
public EmpoweredSubscriber(DisconnectWorker worker, DisconnectHelper helper)
{
_worker = worker;
_helper = helper;
}
public void OnConnected()
{
}
public void OnDisconnected()
{
_worker.DoWork();
_helper.DoHelp();
// more...
}
}
How,does one should call an event declared by interface so that all the classes that has implemented that interface get notified??
For example in structure like this,
public delegate void myDel(int value);
interface IEventCaller{
event myDel myDelEventCall;
}
public Class One : IEventCaller {
public event myDel myDelEventCall;
}
public Class Two : IEventCaller {
public event myDel myDelEventCall;
}
I want both class One and Two to get notify and act as event gets called, I am feeling somewhere I am going wrong direction , is it possible to do?
Actually what you want doesn't involve events. Events would be used by an object implementing IEventCaller to notify some object holding a reference to that object of some change. To invoke something on the object implementing IEventCaller would just require a method, for example Hello();
First, you need code that informs all the objects that implement this interface. To make that possible, you somewhere need to store a list of instances that want to get notified.
One solution would be to create a class that manages that list. Let's say like this
private static List<IEventCaller> eventCallers = new List<IEventCaller>();
public static void AddEventCaller(IEventCaller c)
{
eventCallers.Add(c);
}
public static void RemoveEventCaller(IEventCaller c)
{
eventCallers.Remove(c);
}
public static IEventCaller[] EventCallers
{
get { return eventCallers.ToArray() }
}
Of course this code needs to be thread safe, etc. I'd put all this into a singleton to be globally available.
Then, all objects that implement IEventCallers need to register/unregister accordingly. Thus, I'd also have them Implement IDisposable so that in the constructor you can do
public EventCallable()
{
Singleton.Instance.AddEventCaller(this);
}
and in the Dispose method you can do this:
public void Dispose(bool disposing)
{
Singleton.Instance.RemoveEventCaller(this);
}
Now the code that should notify every instance could just do this:
public void NotifyAll()
{
foreach (IEventCaller caller in Singleton.Instance.EventCallers)
caller.Hello();
}
I think you might be looking at this the other one around.
With events, you want to have an object which is the publisher, which is responsible for publishing the event and saying "hey guys, something just occurred and you should know about it", and you have your subscribers, which are the guys who say "Yo dawg, let me know when that thing occurs, so i can act on it".
What you can do is have the object which is responsible for the event occurring implement your interface:
public class Publisher : IEventCaller
{
public event MyDel MyDeleteEvent;
public void OnDeleteOccured()
{
var myDeleteEvent = MyDeleteEvent;
if (myDeleteEvent != null)
{
MyDeleteEvent(1);
}
}
}
And then have your One and Two objects register to that event occurring, where they pass a method which signature matches the delegate type of MyDel:
public class SubscriberOne
{
public void OnSomethingOccured(int value)
{
Console.WriteLine(value);
}
}
public class SubscriberTwo
{
public void OnSomethingOccured(int value)
{
Console.WriteLine(value);
}
}
And the registration goes:
void Main()
{
var publisher = new Publisher();
var subscriberOne = new SubscriberOne();
var subscriberTwo = new SubscriberTwo();
publisher.MyDeleteEvent += subscriberOne.OnSomethingOccured;
publisher.MyDeleteEvent += subscriberTwo.OnSomethingOccured;
}
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).