Callback interface contract - c#

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

Related

How to decide when i will use Bridge and Decorator pattern in my project and actual conceptual difference both of them

Hey i am working as software developer and starting to understand design pattern, please give me the concept about the bridge and decorator pattern. Already I have gone through the previous post of the related topic but i am not cleared about that please help me!!.
First of all we need to know what is the meaning of Bridge and Decorator pattern??
Bridge: The GOF definition of Bridge pattern is "Decouple an abstraction from its implementation so that the two can vary independently". and this pattern is fall under structural design pattern, why structural because you are changing the structure of our application.
Let's analysis this : Let you implement a business Logic
Class Business
{
public void Operation()
{
//you business logic here
}
}
Class Client
{
Business b=new Business();
b.Operation();
}
please consider in the above "Business" class, is for your application structure that you have implemented and with this structure your client is happy.
Now say after One year your client is requesting you to change their business operation structure as well as previous implemented operational structure remain same for some clients. Now what you will do?
Lets see
Class Business
{
public void Operation()
{
//you business logic here
}
public void NewOperation()
{
//you New business logic here
}
}
Class Client
{
Business b=new Business();
b.NewOperation();
}
Now assume how many changes you need to done for new operation.
Here bridge pattern help a lot;
interface IOperation
{
void operation();
}
public class ConcreteOPeration:Ioperation
{
void operation
{
//you code
}
}
public class NewConcreteOPeration:Ioperation
{
void operation
{
//you new code code
}
}
Public interface OperationBridege
{
void callOperation();
}
Public Class ConcreteBridge:OperationBridege
{
private Ioperation _ioperation;
public ConcreteBridge(Ioperation _operation )
{
this._ioperation=_operation;
}
void callOperation()
{
this._ioperation.operation();
}
}
class client
{
//Ioperation oprtn =New ConcreteOPeration();//NewConcreteOPeration
//if you change to new operation need know change just
the new concreteOperation class
Ioperation oprtn =New NewConcreteOPeration();
OperationBridege bridege =new ConcreteBridge(oprtn);
bridege.callOperation();
}
Any where you using this operation nothing impacted in your application for structural changes for this pattern fall under structural design pattern.
Now we discuss about Decorator pattern.
Decorator: The GoF definition is "Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality."
Lets analysis this if you want to add some additional facilities dynamically in your previously implemented class then GOF suggested at this situation we will must use decorator design pattern.
Let see an example
public interface IComponent
{
void Operation();
}
public class ConcreteComponent:IComponent
{
public void Operation()
{
Console.WriteLine("This is the main functionality!!!");
}
}
public class Decoretor:IComponent
{
protected IComponent component;
public void SetComponent(IComponent _component)
{
this.component = _component;
}
public virtual void Operation()
{
component.Operation();
}
}
public class ConcreteDecoratorA : Decoretor
{
public override void Operation()
{
base.Operation();
}
}
public class ConcreteDecoratorB : Decoretor
{
public override void Operation()
{
base.Operation();
Show();
}
public void Show()
{
Console.WriteLine("Additional resposiblity attached");
}
}
class Program
{
static void Main(string[] args)
{
IComponent c = ComponentObjCreator.ComponentCreator();
//Decoretor d = new ConcreteDecoratorA();//In this class have basic //functionalities
Decoretor d = new ConcreteDecoratorB();//in this class has some additional
functionalities
d.SetComponent(c);
d.Operation();
}
}
Actually here we decorated our application structure with some new functionalities
and we are implemented in the "ConcreteDecoratorB" class that's why we are called this decorator business pattern.it's also fall under structural design pattern.
I have found Christopher Okhravi a YouTube VLogger to have posted some interesting videos about various design patterns, including Bridge & Decorator.
He does so in a quite entertaining (considering the subject) and presents it in a fairly easy to understand manner.
Decorator Pattern:
https://youtu.be/GCraGHx6gso
Bridge Pattern:
https://youtu.be/F1YQ7YRjttI
You can also check out this website:
https://www.oodesign.com/
Both of them are in the structural patterns category in the Gof.
we use the Bridge Pattern when we need to have some separated logic that when we need to use each of them. for example, you have software to send multiple types of notification to users like SMS, Email and sets. here we use the Bridge Pattern.
On the other hand when we need to implement a system to add some specific behavior to object we use a Decorator pattern. For example, you decide to make an IceCream Machine with multiple choosable things like Honey, Bread, nuts and ... here we use the Decorator pattern (Also known as Wrapper).
There is some useful information on below links
Decorator Design Pattern
Bridge Deign Pattern

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

How to get list of currently instantiated instances of some dependency in Castle Windsor?

Suppose I have a component Bar that does Foo and notifies about that calling FooHappened method on all services implementing IFooConsumer interface.
I can write Bar like this
class Bar
{
public Bar(IEnumerable<IFooConsumer> fooConsumers) { ... }
public void Foo()
{
// foo-ing
foreach (var f in _fooConsumers) f.FooHappened();
}
}
It will work, but instantiating Bar will instantiate all possible IFooConsumers. What if I need to notify only those IFooConsumers that exist at the moment when Foo happened?
Is there a way to get some kind of tracker that knows about all instantiated instances of IFooConsumer?
I could probably write one myself via subscribing to IWindsorContainer.Kernel.ComponentCreated, but I'm interested if something like that exists? Or maybe there's another way to solve my issue?
You can create a simple facility like the one showing below, that will do the event registration every time a components get's instantiated. The code below here is for using Winsor with Caliburn.Micro. This will also make sure that events get deregistered, which will otherwise result in weird behaviour. In your case I would not have Bar directly fire the event's to all the classes, but rather use a singleton component (like IEventAggregator below) to fire events to multiple classes. This will also make sure that events get deregistered, which will otherwise result in weird behaviour. In the code every class that derives from IHandle will receive events. You can change this according to your needs.
If you have any questions just let me know.
class EventRegistrationFacility : AbstractFacility
{
private IEventAggregator _eventAggregator;
protected override void Init()
{
Kernel.ComponentCreated += ComponentCreated;
Kernel.ComponentDestroyed += ComponentDestroyed;
}
void ComponentCreated(Castle.Core.ComponentModel model, object instance)
{
if (!(instance is IHandle)) return;
if (_eventAggregator == null) _eventAggregator = Kernel.Resolve<IEventAggregator>();
_eventAggregator.Subscribe(instance);
}
void ComponentDestroyed(Castle.Core.ComponentModel model, object instance)
{
if (!(instance is IHandle)) return;
if (_eventAggregator == null) return;
_eventAggregator.Unsubscribe(instance);
}
}
===EDIT====
Combining this with the bouncer as described by Sammy:
public interface IBouncer {
IEnumerable<IFooConsumer> WhoIsInside {get;}
void WelcomeTo(IFooConsumer consumer);
void EscortOut(IFooConsumer consumer);
}
public class Bouncer {
private IList<IFooConsumer> _inside {get;}
void WelcomeTo(IFooConsumer consumer) {
_inside.Add(consumer);
}
void EscortOut(IFooConsumer consumer);
_inside.Remove(consumer);
}
IEnumerable<IFooConsumer> WhoIsInside {
get {
return _inside;
}
}
public Consumer: IFooConsumer {
FooHappened() {
// Do something.
}
// no need to implement constructor/dispose
}
class Bar
{
public Bar(IBouncer bouncer) { ... }
public void Foo()
{
// foo-ing ==> alernatively create a function on Bouncer that does this. And keep WhoIsInside private.
foreach (var f in bouncer.WhoIsInside) f.FooHappened();
}
}
class BouncerRegistrationFacility : AbstractFacility
{
private IBouncer _bouncer
protected override void Init()
{
Kernel.ComponentCreated += ComponentCreated;
Kernel.ComponentDestroyed += ComponentDestroyed;
}
void ComponentCreated(Castle.Core.ComponentModel model, object instance)
{
if (!(instance is IFooConsumer)) return;
if (_bouncer == null) _bouncer = Kernel.Resolve<IEventAggregator>();
_bouncer.WelcomeTo(instance);
}
void ComponentDestroyed(Castle.Core.ComponentModel model, object instance)
{
if (!(instance is IFooConsumer)) return;
if (_bouncer == null) return;
_bouncer.EscortOut(instance);
}
}
Allthough you need some more code for writing the facility, there is no need for FooConsumers to register/unregister themselves. As the registration code must originally be written in all FooConsumers it tends to repeat. In this way the subscription/unsubscription is done as a commission/decommission requirement and only needs to be dealt with once.
P.S. Code is written in notepad and might contain compile errors.
I think that putting the crux of knowing which objects are instantiated on Castle Windsor is not the best way forward; you will certainly need to access some container methods and doing so will link your components to Castle, which shouldn't happen.
What I'd recommend instead is to create a component IBouncer. That component would be injected as singleton in all IFooConsumer which would call it upon being created and disposed (dispose being one option, you could use other methods)
public interface IBouncer {
IEnumerable<IFooConsumer> WhoIsInside {get;}
void WelcomeTo(IFooConsumer consumer);
void EscortOut(IFooConsumer consumer);
}
public Consumer: IFooConsumer {
public Consumer(IBouncer bouncer) {
bouncer.WelcomeTo(this);
}
public Dispose() {
bouncer.EscortOut(this); // dispose pattern ommitted
}
}
Now instead of passing the list of IFooConsumer to your Bar, just add the IBouncer to it and ask which consumers are inside.
class Bar
{
public Bar(IBouncer bouncer) { ... }
public void Foo()
{
// foo-ing
foreach (var f in bouncer.WhoIsInside) f.FooHappened();
}
}

Is Service Locator an anti pattern in a pluggable architecture?

I know this question might look like it's a duplicate but please let me explain.
So I created several components that use a pluggable architecture, basically I can freely add new implementations and they will be injected and processed automatically for me. This is really handy in several scenarios.
I'm going to talk about the simplest one, validating components.
One of the reasons to use a design like this is that I like to expose my roles explicitly as explained by Udi Dahan
Basically I have code like this:
public interface IValidatorRuner
{
void Run<TTarget>(TTarget target);
}
public class ValidatorRunenr : IValidatorRuner
{
private readonly IServiceLocator _serviceLocator;
public ValidatorRunenr(IServiceLocator serviceLocator)
{
_serviceLocator = serviceLocator;
}
public void Run<TTarget>(TTarget target)
{
// this is the dynamic/pluggable phase
// is this an antipattern???
var foundValdiators = _serviceLocator.GetAllInstances<IValidator<TTarget>>();
foreach (var valdiator in foundValdiators)
{
valdiator.IsSatisfiedBy(target);
}
}
}
This code lets me expose my validation rules explicitly like this:
//this will allow me to create validators in this way
//and they will be automatically injected and resolved for me
//(easy, to read, easy to write, easy to test, pff I could even smoke this validator easily)
public class OneValdiationRuleExplicitlyExposedAndEasyToTest : IValidator<Person>
{
public bool IsSatisfiedBy(Person target)
{
return target.Age > 18;
}
}
public class Person
{
public int Age { get; set; }
}
public interface IValidator<TTarget>
{
bool IsSatisfiedBy(TTarget target);
}
And I will use this code like this:
//usage
public class SomeCommandHandler
{
private readonly IValidatorRuner _validatorRuner;
public SomeCommandHandler(IValidatorRuner validatorRuner)
{
_validatorRuner = validatorRuner;
}
public void SomeMethod()
{
_validatorRuner.Run(new Person{Age = 16});
}
}
Validation was just one example, I also use it to fire domain events and to run pipelines and filters in the same pluggable way
Is using the service locator in this way an anti-pattern?
I know I might be hiding some dependencies, but the thing is that the dependencies are dynamically injected and discovered when the application initializes (Composition root)
Your thoughts will be greatly appreciated
In my opinion, the primary issue with your code sample is that the service locator is itself injected into the implementation of ValidatorRunner. For me, this is an anti-pattern, but perhaps not the one you're asking about.
Any answer I might give boils down to the capabilities of your service locator implementation. But for sure it should not be passed into the constructor of your class. Instead, the service locator should itself pass these things in when you ask it for an implementation of "IValidatorRuner"
As an example, you can inject a factory that knows how to load the dynamic validator instances for a given type.
If anyone is interested, I found a way to remove the ServiceLocator in my objects and still dynamically load/discover dependencies at run time.
The way I solved it was by registering my components in my DI container in the following way (using the Mediator pattern):
Binding mediator (shortbus) with/to ninject
var kernel = new StandardKernel();
kernel.Bind(x => x.FromThisAssembly()
.SelectAllClasses()
.InheritedFromAny(
new[]
{
typeof(IValidatorRunner<>)
})
.BindDefaultInterfaces());
And my final implementation looks like:
public interface IValidatorRuner<in TTarget>
{
void Run(TTarget target);
}
public class ValidatorRunenr<TTarget> : IValidatorRuner<TTarget>
{
private readonly IEnumerable<IValidator<TTarget>> _validators;
public ValidatorRunenr(IEnumerable<IValidator<TTarget>> validators)
{
_validators = validators;
}
public void Run(TTarget target)
{
foreach (var valdiator in _validators)
{
valdiator.IsSatisfiedBy(target);
}
}
}
Usage
//usage
public class SomeCommandHandler
{
private readonly IValidatorRuner<OneValdiationRuleExplicitlyExposedAndEasyToTest> _validatorRuner;
public SomeCommandHandler(IValidatorRuner<OneValdiationRuleExplicitlyExposedAndEasyToTest> validatorRuner)
{
_validatorRuner = validatorRuner;
}
public void SomeMethod()
{
_validatorRuner.Run(new Person{Age = 16});
}
}
In few words, by registering an opened generic type, my container resolves any call to that type creating a concrete-closed-generic-type instance at runtime for me.
As you can see in the usage, I do not have to create a specific concrete-closed-generic type of IValidatorRunner<OneValdiationRuleExplicitlyExposedAndEasyToTest> because the container creates one for me.
And there you go, now I'm happy because I removed the service locator from my domain objects =)

Domain Events pattern single point to queue events

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.

Categories