Domain Events pattern single point to queue events - c#

I put a question here: Raising Domain Events For Multiple Subscribers and the answer led me to the following pattern where I can have an IEventPublisher like so:
public interface IEventPublisher<T>
{
void Publish(T data);
}
and an IEventSubscriber like so:
public interface IEventSubscriber<T>
{
void Handle(T data);
}
The problem with this is that I need to pass an instance of each publisher to a constructor like so:
public Service(IEventPublisher<ThingyChangedEvent> publisherThingyChanged)
{
// Set publisher to local variable
}
// then call this in a method
_publisherThingyChanged.Publish(new ThingyChangedEvent { ThingyId = model.Id});
What I would ideally like to be able to do is have a generic publisher which contains any IEventPublishers so I can call somthing like:
_genericPublisher.Publish(new ThingyChangedEvent { ThingyId = model.Id});
I can't figure out how to do this though as I can't pass a collection of IEventPublisher without defining T as in this example as ThingyChangedEvent whereas what I want is to determine the publisher based on the type that is passed to the generic publisher.
Any suggestions much appreciated.
EDIT:
OK using the answer below and some info from here: http://www.udidahan.com/2009/06/14/domain-events-salvation/ I came up with the following but it's not quite there:
public interface IEventManager
{
void Publish<T>(T args) where T : IEvent;
}
public class EventManager : IEventManager
{
Autofac.ILifetimeScope _container;
public EventManager(Autofac.ILifetimeScope container)
{
_container = container;
}
//Registers a callback for the given domain event
public void Publish<T>(T args) where T : IEvent
{
var subscribersProvider = _container.Resolve<IEventSubscribersProvider<T>>();
foreach (var item in subscribersProvider.GetSubscribersForEvent())
{
item.Handle(args);
}
}
}
I can now take an instance of IEventManager eventManager in a constructor resolved by autofac and call it as follows:
_eventManager.Publish<ThingyChangedEvent>(new ThingyChangedEvent() { ThingyId = Guid.NewGuid() });
Here is what I don't like about this solution:
I don't want to take an instance of ILifetimeScope in the constructor, I want to be able to take a collection of IEventSubscribersProvider but autofac won't resolve this if I ask for say:
IEnumerable<IEventSubscribersProvider<IEvent>>
I can only resolve it if I pass the type to the Publish and call:
Resolve<IEventSubscribersProvider<T>>.
The second issue is not a huge deal but would be nice to be able to call publish without having to pass the type as well like so:
_eventManager.Publish(new ThingyChangedEvent() { ThingyId = Guid.NewGuid() });
I think if anyone has any suggestions of how to solve these two issues, particularly issue 1 as I don't like putting a dependency on Autofac in different projects. The only thing I can come up with is a manager class of some kind which explicitly takes what I need as follows:
public SomeConstructor(
IEventSubscribersProvider<ThingyChangedEvent> thingChangedSubscribeProviders,
IEventSubscribersProvider<SomeOtherEvent> someOtherSubscribeProviders,
etc....)
{
// Maybe take the EventManager as well and add them to it somehow but would be
// far easier to take a collection of these objects somehow?
}
Many thanks for any suggestions.
EDIT 2
After a lot of research and looking at this Autofac Generic Service resolution at runtime I am not sure I can achieve what I want to. The best solution I can come up with is this:
public interface IEventSubscribersProviderFactory : Amico.IDependency
{
IEventSubscribersProvider<T> Resolve<T>() where T : IEvent;
}
public class EventSubscribersProviderFactory : IEventSubscribersProviderFactory
{
Autofac.ILifetimeScope _container;
public EventSubscribersProviderFactory(Autofac.ILifetimeScope container)
{
_container = container;
}
public IEventSubscribersProvider<T> Resolve<T>() where T : IEvent
{
return _container.Resolve<IEventSubscribersProvider<T>>();
}
}
And then have the EventManager take IEventSubscribersProviderFactory in the constructor to remove the dependency on Autofac from that project.
I'll go with this for now but hopefully will find a better solution int the long term.

It can get a bit complex when you have to deal with multiple types of events. As you've probably noticed you can't just use a derived generic type and expect to use it like a base generic--.NET variance doesn't support that where you'd want to use it.
You need a "base" type that would be the minimum (or most narrow) type that you'd accept as an "event". I generally use a marker interface like public interface IEvent{}. You could, of course, derive from Object; but I find it useful to have marker interfaces to make the fact that you're subscribing or publishing an "event" explicit (and means you can't just publish any type of object, just "events").
From the handling of multiple type aspect, you need to write a class to do the narrowing (taking a derived type and "publish" the same object cast to the derived type). Even with that you need to route your events through an appropriate instance of a narrower (to "get around" the variance limitations). Then, of course, you could have multiple subscribers to the same event type; so you need something to route an event to the multiple subscribers. This is generally called a Multiplexor, which would be a specialization of IEventPublisher. You'll need one multiplexor per event type--which would use the narrower. Which multiplexor to use for a given event depends on type, so that collection of multiplexors would be managed by a dictionary so you can look them up by type. Then, to publish an event to multiple subscribers, by type, you simple look up the multiplexor and call its IEventPublisher.Publish method. And something that manages the multiplexors is a type of IEventPublisher and is generally called a Dispatcher (some might call it a router).
For example:
public class NarrowingSubscriber<TBase, TDerived> : IEventSubscriber<TBase>
where TDerived : TBase
where TBase : IEvent
{
private IEventSubscriber<TDerived> inner;
public NarrowingSubscriber(IEventSubscriber<TDerived> inner)
{
if (inner == null) throw new ArgumentNullException("inner");
this.inner = inner;
}
public void AttachSubscriber(IEventSubscriber<TDerived> subscriber)
{
inner = subscriber;
}
public void Handle(TBase data)
{
inner.Handle((TDerived)data);
}
}
public class Multiplexor<T> : IEventSubscriber<T> where T : IEvent
{
private readonly List<IEventSubscriber<T>> subscribers =
new List<IEventSubscriber<T>>();
public void AttachSubscriber(IEventSubscriber<T> subscriber)
{
subscribers.Add(subscriber);
}
public void RemoveSubscriber(IEventSubscriber<T> subscriber)
{
subscribers.Remove(subscriber);
}
public void Handle(T data)
{
subscribers.ForEach(x => x.Handle(data));
}
}
public class Dispatcher<TBase> : IEventPublisher<TBase> where TBase : IEvent
{
private readonly Dictionary<Type, Multiplexor<TBase>> subscriptions =
new Dictionary<Type, Multiplexor<TBase>>();
public void Publish(TBase data)
{
Multiplexor<TBase> multiplexor;
if (subscriptions.TryGetValue(data.GetType(), out multiplexor))
{
multiplexor.Handle(data);
}
}
public void Subscribe<TEvent>(IEventSubscriber<TEvent> handler)
where TEvent : TBase
{
Multiplexor<TBase> multiplexor;
if (!subscriptions.TryGetValue(typeof(TEvent), out multiplexor))
{
multiplexor = new Multiplexor<TBase>();
subscriptions.Add(typeof(TEvent), multiplexor);
}
multiplexor.AttachSubscriber(new NarrowingSubscriber<TBase, TEvent>(handler));
}
}
So, you're basically publishing 4 times. Once to the dispatcher, once to the multiplexor, once to the narrower, and once to the non-infrastructure subscriber. If you had two subscribers (EventOneEventSubscriber and EventTwoEventSubscriber) that subscribed to two types of events (EventOne and EventTwo) then you might create a dispatcher and publish events like this:
var d = new Dispatcher<IEvent>();
var eventTwoSubscriber = new EventTwoEventSubscriber();
d.Subscribe(eventTwoSubscriber);
var eventOneSubscriber = new EventOneEventSubscriber();
d.Subscribe(eventOneSubscriber);
d.Publish(new EventOne());
d.Publish(new EventTwo());
Of course, the events would derive from IEvent:
public class EventOne : IEvent
{
}
public class EventTwo : IEvent
{
}
This particular limitation does not take into account dispatching events multiple times. For example, I could have on subscriber to EventOne and one subscriber for IEvent. This implementation just publishes to the EventOne subscriber if an EventOne object is published through the dispatcher--it wouldn't publish to the IEvent subscriber. I'll leave that as an exercise for the reader :)
Update:
If what you're hoping to do is to auto-wire the subscribers without having to construct them (I don't see much value in this, consider a Composition Root) then you can add a fairly simple method to the Dispatcher (or elsewhere, if needed) to subscribe all compatible subscribers:
public void InitializeSubscribers()
{
foreach (object subscriber in
from assembly in AppDomain.CurrentDomain.GetAssemblies()
from type in assembly.GetTypes()
where !type.IsAbstract && type.IsClass && !type.ContainsGenericParameters &&
type.GetInterfaces().Any(t => t.IsGenericType &&
t.GetGenericTypeDefinition() == typeof (IEventSubscriber<>))
select type.GetConstructor(new Type[0])
into constructorInfo
where constructorInfo != null
select constructorInfo.Invoke(new object[0]))
{
Subscribe((dynamic) subscriber);
}
}
in which you'd use as follows:
var d = new Dispatcher<IEvent>();
d.InitializeSubscribers();
...using a container to resolve the Dispatcher<T> object, if you want.

Related

Dependency Injection of IEnumerable of Open Generic

I am trying to optimize my code for the injection of a list of classes, that implement an interface of
IEventHandler<TEvent>.
I have the following structure:
public interface IEventHandlerMarker { }
public interface IEventHandler<in TEvent> : IEventHandlerMarker where TEvent : IEvent
{
Task Handle(TEvent eventItem);
}
public interface IEvent
{
public DateTime Timestamp { get; set; }
}
I register the marker interface IEventHandlerMarker in DI and when accessing the handlers, I currently do the following:
public EventPublisherService(IEnumerable<IEventHandlerMarker> eventHandlers)
{
// Check and and all event handlers
foreach (IEventHandlerMarker item in eventHandlers)
{
AddEventHandler(item);
}
}
In my AddEventHandler method, I filter those to IEventHandler<> like this:
Type handlerType = eventHandlerMarker.GetType().GetInterfaces()
.FirstOrDefault(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IEventHandler<>));
So far everything works, but I'd like to get rid of the marker interface and the filter logic. So I changed the registration of handlers to the following method and this seems to work as expected:
public static IServiceCollection AddEventHandlers(this IServiceCollection serviceDescriptors, params Assembly[] handlerAssemblies)
{
Type genericHandlerType = typeof(IEventHandler<>);
foreach (var implementationType in genericHandlerType.GetTypesWithGenericInterfacesInAssemblies(handlerAssemblies))
{
Type interfaceType = implementationType.GetGenericInterfaceType(genericHandlerType);
serviceDescriptors.AddSingleton(interfaceType, implementationType);
}
return serviceDescriptors;
}
public static List<Type> GetTypesWithGenericInterfacesInAssemblies(this Type source, params Assembly[] assemblies)
{
return assemblies
.SelectMany(currentAssembly => currentAssembly.GetTypes()
.Where(type => type.GetInterfaces().Any(
interfaceItem => interfaceItem.IsGenericType
&& interfaceItem.GetGenericTypeDefinition().Equals(source))))
.ToList();
}
I changed the constructor of EventPublisherService to the following:
public EventPublisherService(IServiceProvider serviceProvider)
{
Type ienumerableOfIEventHandlerType = typeof(IEnumerable<>).MakeGenericType(typeof(IEventHandler<>));
object result = serviceProvider.GetService(ienumerableOfIEventHandlerType);
}
But result always turns out to be null.
I googled and checked some articles on Stackoverflow and came across the following article:
https://stackoverflow.com/a/51504151/1099519
I am not sure if this is the same case, as I am not using a factory.
Versions used: .NET Core 3.1 and Autofac 4.9.4 for the Dependency Injection management.
Register all handlers automatically as shown in this question/answer:
builder.RegisterAssemblyTypes(AppDomain.CurrentDomain.GetAssemblies())
.AsClosedTypesOf(typeof (IEventHandler<>)).AsImplementedInterfaces();
When you have TEvent and want to find all handlers, get them by constructing the concrete interface type as follows:
Type generic = typeof(IEnumerable<IEventHandler<>>);
Type[] typeArgs = { typeof(TEvent) }; // you might get the Type of TEvent in a different way
Type constructed = generic.MakeGenericType(typeArgs);
You should cache this in an dictionary to avoid doing reflection at every event dispatch.
Once you have the constructed concrete interface type, you can ask Autofac for all implementations of that interface:
var handlers = container.Resolve(constructed);
Now, the problem is that with the handler instances you can only call the Handle method using Invoke (reflection). This is a performance issue, but it's unrelated to how you register and resolve the handlers. It's related to the fact that you need to call a concrete method from an object. To avoid using reflection you need compiled code that calls the concrete method (note that using Generics also creates concrete compiled code for each Type).
I can think of two ways of getting compiled code to do this calls:
Manually writing a delegate which casts your object handler instance into a concrete type for every TEvent type that you have. Then store all these delegates in a dictionary so you can find them at runtime based on TEvent type and call it passing the handler instance and the event instance. With this approach, for every new TEvent that you create, you need to create a matching delegate.
Doing a similar thing as before but by emitting the code at startup. So, same thing, but the whole creation of the delegates is automatic.
Update
Based on the repository shared by the OP, I created a working version. The main code, to resolve the handlers and call them is in the EventPublisherService class
public class EventPublisherService : IEventPublisherService
{
private readonly ILifetimeScope _lifetimeScope;
public EventPublisherService(ILifetimeScope lifetimeScope)
{
_lifetimeScope = lifetimeScope;
}
public async Task Emit(IEvent eventItem)
{
Type[] typeArgs = { eventItem.GetType() };
Type handlerType = typeof(IEventHandler<>).MakeGenericType(typeArgs);
Type handlerCollectionType = typeof(IEnumerable<>).MakeGenericType(handlerType);
var handlers = (IEnumerable<object>)_lifetimeScope.Resolve(handlerCollectionType);
var handleMethod = handlerType.GetMethod("Handle");
foreach (object handler in handlers)
{
await ((Task)handleMethod.Invoke(handler, new object[] { eventItem }));
}
}
}
Note that as specified in the original answer, this solution does not include the very necessary performance optimisations. The minimum that should be done is to cache all the types and MethodInfos so they don't need to be constructed every time. The second optimisation would be, as explained, to avoid using Invoke, but it's more complicated to achieve and IMO it requires a separate question.
With autofac you can inject an IEnumerable<IEventHandler<TEvent>> and Autofac should resolve a List of all implementations of it.
https://autofaccn.readthedocs.io/en/latest/resolve/relationships.html

How to find all the interfaces that extend a base interface on a given object?

I'm trying to create a crude/basic event Subscribe/Publish system just to experiment.
I created a base IEventListener interface, then a generic IEventListener<T> : IEventListener interface on top of that, which has a function OnEvent(T eventParam)
I then created a test class that implemented IEventListener<string> and IEventListener<int>
I thought that by passing it through the following:
Dictionary<Type, List<object>> _listenersByType = new Dictionary<Type, List<object>>();
foreach(Type interfaceType in listener.GetType().GetInterfaces())
{
if(interfaceType is IEventListener)
{
AddSubscriber(interfaceType.GetGenericTypeDefinition(), listener);
}
}
I could create a look up of Event Types to Objects to cast and publish the events to. However, when stepping through. I see it loop all the interfaces, I can see the type name is "IEventListener" but the condition is never true, and never adds my listener to the dictionary.
Pastebin of full code
Through means of which I am unsure (I poked around in the debugger), this fixes it:
foreach(Type interfaceType in listener.GetType().GetInterfaces())
{
if(interfaceType.GetInterfaces().Contains(typeof(IEventListener)))
{
AddSubscriber(interfaceType.GetGenericArguments()[0], listener);
}
}
But I cannot tell you why I have to check the interfaces, of the interface. Or why I have to call interfaceType.GetGenericArguments()[0] instead of interfaceType.GetGenericTypeDefinition().
Part of me feels like this code is bad and I've got a design issue here. I would never expect the solution to be so... Ugly.
You could just ask the object itself if it implemets interface. For exampl i have created fake class:
public class SListener<T> : IEventListener<T>
{
public void OnEvent(T eventParam)
{
}
}
and object of it
var s = new SListener<string>();
if i ask
bool t = (s is IEventListener);
it is true.
So your subscribe mthod could be like :
public void Subscribe(object listener)
{
if(listener is IEventListener)
{
AddSubscriber(interfaceType.GetGenericTypeDefinition(), listener);
}
}

All classes with particular Interface should be notify by event

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;
}

Callback interface contract

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

Reusable non generic method for generic methods

I have the following base interface
public interface IHandler{
void Handle(IMessage message);
}
and an generic interface inheriting the base interface
public interface IHandler<TMessage> : IHandler where TMessage : IMessage{
void Handle(TMessage message);
}
My classes can implement the interface IHandler<TMessage> mutiple times. IMessage is an base interface for messages and isn´t relevant here. Currently i´m implementing the interfaces as follows.
public class ExampleHandler : IHandler<ExampleMessage>, IHandler<OtherExampleMessag>{
void IHandler.Handle(IMessage message){
ExampleMessage example = message as ExampleMessage;
if (example != null) {
Handle(example);
}
else {
OtherExampleMessage otherExample = message as OtherExampleMessage;
if (otherExample != null) {
Handle(otherExample);
}
}
public void Handle(ExampleMessage) {
//handle message;
}
public void Handle(OtherExampleMessage) {
//handle message;
}
}
What bothers me is the way i have to implement the Handle(IMessage) method, cause in my opinion its many redundant code, and i have to extend the method each time when i implement a new IHandler<TMessage> interface on my class.
What i´m looking for is a more generic way to implement the Handle(IMessage) method (maybe in a base class for Handlers), but i´m currently stuck how to do that.
You can use the new dynamic keyword to move the overload resolution to the DLR:
void IHandler.Handle(IMessage message)
{
dynamic d = message;
Handle(d);
}
Please note that this will fail at runtime with a RuntimeBinderException if the message passed in is not valid for your class.
To avoid this exception you can add a Handler for all unknown message types:
private void Handle(object unknownMessage)
{
// Handle unknown message types here.
}
To implement IHandler.Handle in a base class, you need to do a little bit more work:
public class BaseHandler : IHandler
{
void IHandler.Handle(IMessage message)
{
dynamic d = message;
Handle(d);
}
private void Handle<TMessage>(TMessage message) where TMessage : IMessage
{
var handler = this as IHandler<TMessage>;
if(handler == null)
HandleUnknownMessage(message);
else
handler.Handle(message);
}
protected virtual void HandleUnknownMessage(IMessage unknownMessage)
{
// Handle unknown message types here.
}
}
Your specific handler would than look like this:
public class ExampleHandler : BaseHandler,
IHandler<ExampleMessage>,
IHandler<OtherExampleMessage>
{
public void Handle(ExampleMessage message)
{
// handle ExampleMessage here
}
public void Handle(OtherExampleMessage message)
{
// handle OtherExampleMessage here
}
}
This code now works like this:
The DLR calls the generic BaseHandler.Handle<TMessage> method with the real message type, i.e. TMessage will not be IMessage but the concrete message class like ExampleMessage.
In this geneirc handler method, the base class tries to case itself to a handler for the specific message.
If that is not successful, it calls HandleUnknownMessage to handle the unknown message type.
If the cast is successful, it calls the Handle method on the specific message handler, effectifly delegating the call to the concrete Handler implementation.
A reasonable way would be some judicious use of reflection:
var method = this.GetType().GetMethod("Handle", new[] { message.GetType() });
if (method != null) {
method.Invoke(this, new[] { message });
}
If you are doing this so much that performance is a problem you could cache the results of the test for a massive improvement.
You stuck because your class (in the question) does more than one thing. It deals with ExampleMessage and OtherExampleMessage. I suggest you create one class to handle one thing.
Example:
public class ExampleHandler : IHandler<ExampleMessage>
and
public class OtherExampleHandler : IHandler<OtherExampleMessag>
From my understanding, you want to have a class to handle some kind of events. In this case, you may have to use Observer pattern to notify each Handler when something happen and let they do their work.
The interfaces are saying that you have an instance that provides N services. Sure the services are similar but as they are for different types they are independent services. So your detecting a 'code smell'. The smell is 'why a common method for different services?'.
So are the services different enough to justify the generic interface declarations? The fundamental here is 'duplication'. Refactor out the duplication. Duplication is BAD. Once you move the duplicate stuff out then the answer will be self evident.
To put this another way, get rid of the common method and handle each in its own method ... the duplication is what you want to move out to another class. If so, think injection.
Love your smell detection!

Categories