项目作者: JeyDotC

项目描述 :
A very simple event emitter
高级语言: C#
项目地址: git://github.com/JeyDotC/Events.git
创建时间: 2016-02-01T00:55:54Z
项目社区:https://github.com/JeyDotC/Events

开源协议:GNU General Public License v2.0

下载


Events

This is a small library which purpose is to give a very simple implementation of the observer pattern.

Rationale

This library was created for the need of a simple way to say “hay, this happened” without worrying about “who is listening” or “how is this executing”, just

  1. emitter.Emit(myEvent);

And let the gossip classes do their job.

That’s how I came to the idea that our dispatcher (the EventEmitter class) needed a way to get rid of those affairs, then, the IObserverStorage and the IObserversInvoker came into play. One finds the neighbours and the other spreads the gossip.

Install

Use Nuget

  1. PM> Install-Package Events

Compile it, it doesn’t need to install or configure weird things ;)

Usage

First, Define your event:

  1. // Just a Plain Old C# Class
  2. public class HelloWorldEvent {
  3. public string Data {get; set; }
  4. }

Second, create your observers:

  1. public class January : IEventObserver<HelloWorldEvent>{
  2. void On(HelloWorldEvent evnt){
  3. evnt.Data += "Traveling time with my fedora hat. ";
  4. }
  5. }
  6. public class February : IEventObserver<HelloWorldEvent>{
  7. void On(HelloWorldEvent evnt){
  8. evnt.Data += "Catching bullets with my bare hands. ";
  9. }
  10. }

Third, create someone to find your observers:

  1. IObserverStorage observerStorage = new MemoryObserverStorage(
  2. new January(),
  3. new February()
  4. //, and the other...
  5. );

Fourth, contract someone spread your message:

  1. IObserversInvoker invoker = new SequentialObserverInvoker(); //<-- This is the default guy.

And finally instantiate the emitter and emit the event:

  1. var emitter = new EventEmitter(observerStorage, invoker); // or just new EventEmitter(observerStorage);
  2. var myEvent = new MyEvent{ Data = "Hello observers, what's your status? " };
  3. emitter.Emit(myEvent);

Wrapping up, this is what you do:

  1. // Create the storage
  2. IObserverStorage observerStorage = new MemoryObserverStorage(
  3. new January(),
  4. new February()
  5. //, and the other...
  6. );
  7. // Create the invoker
  8. IObserversInvoker invoker = new SequentialObserverInvoker();
  9. //Configure the emitter
  10. var emitter = new EventEmitter(observerStorage, invoker); // or just new EventEmitter(observerStorage);
  11. // Tell the world how cool are you
  12. var myEvent = new MyEvent{ Data = "Hello observers, what's your status? " };
  13. emitter.Emit(myEvent);

But man, I still in need of instantiating all my observers!

Don’t worry, there is an AssemblyScanningOberverStorage that goes inside your assemblies and finds all those gossip observers for you. Just make sure you instantiate that class only once.

  1. // Create the storage
  2. IObserverStorage observerStorage = new AssemblyScanningOberverStorage(
  3. // optionally add assembly names: "My.Cool.Assembly", "My.Cool.Assembly2" ...
  4. );
  5. // Create the invoker
  6. IObserversInvoker invoker = new SequentialObserverInvoker();
  7. //Configure the emitter
  8. var emitter = new EventEmitter(observerStorage, invoker); // or just new EventEmitter(observerStorage);
  9. // Tell the world how cool are you
  10. var myEvent = new MyEvent{ Data = "Hello observers, what's your status? " };
  11. emitter.Emit(myEvent);

Hey, my observers are kind of… fat

Then all you need is another invoker, the ParallelsObserverInvoker which calls your observers with the Parallels static class.

  1. // Create the invoker
  2. IObserversInvoker invoker = new ParallelsObserverInvoker(new ParallelOptions
  3. {
  4. MaxDegreeOfParallelism = 4
  5. });
  6. //Configure the emitter
  7. var emitter = new EventEmitter(observerStorage, invoker);
  8. // Tell the world how cool are you
  9. var myEvent = new MyEvent{ Data = "Hello observers, what's your status? " };
  10. emitter.Emit(myEvent);

In the future I’m planning to create a HangFire invoker for really heavy observers.

My boss says “cache al the things!”

To satisfy your boss, we got an adapter class: CachedObserverStorage which caches the results of getting the observers for each event:

  1. // Create the storage
  2. IObserverStorage heavyStorage = new AssemblyScanningOberverStorage(
  3. // optionally add assembly names: "My.Cool.Assembly", "My.Cool.Assembly2" ...
  4. );
  5. // create your cache
  6. ObjectCache cache = new MemoryCache("MyObservers");
  7. IObserverStorage cachedStorage = new CachedObserverStorage(cache, heavyStorage);
  8. //Configure the emitter
  9. var emitter = new EventEmitter(cachedStorage);
  10. // Tell the world how cool are you
  11. var myEvent = new MyEvent{ Data = "Hello observers, what's your status? " };
  12. emitter.Emit(myEvent);

Get creative

This library lets you be creative in how to implement the aspects of the emitter, as it depends on a couple of interfaces, for example, you could create an observer storage that finds its observers from a Database or from CsScript files. Or an observer invoker that decides if an observer is to be executed now or scheduled for later (Quartz, hangfire, NServicebus)?

Next things I’ll do

  • Publish to nuget.
  • HangFire invoker (I need it for my job, that’s why it is first).
  • Some handy extension methods. (myStorage.Cached(); to name one).
  • Ninject integration.