www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.announce - Event Dispatcher

reply Eugene Wissner <belka caraus.de> writes:
Hey,

I wrote some time ago I'm working on the rewriting some parts of 
Symfony web framework from PHP to D. One component is pretty 
small and is already ready. It is an Event Dispatcher:
https://github.com/caraus-ecms/caraus (submodule 
caraus:eventdispatcher).

Event dispatchers make it possible to write extensible 
applications. You can register events in different places of your 
application and attach callbacks to them. It is similar to 
signals, but you have a central instance aware of all events and 
callbacks (Mediator pattern: 
https://en.wikipedia.org/wiki/Mediator_pattern).

It isn't very useful on its own, since the event dispatcher 
should be passed everywhere but it can be used, for example,  
with a DI container like poodinis. Since frameworks like 
https://github.com/Skadi-d/Skadi.d had "Event Dispatcher" in its 
TODO, I decided to write this Announce if something finds it 
useful.

In the following lines I will only describe how it works and what 
is for. You can find the example I describe here: 
https://github.com/caraus-ecms/caraus/blob/master/examples/eventdispatcher/source/app.d

We want to extend a hello world program:


import std.stdio;

class HelloWorld
{
	void hello()
	{
		writeln("Hello world!");
	}
}

void main()
{
	auto helloWorld = new HelloWorld;
	helloWorld.hello();
}


We want that people can attach their own messages before "Hello 
world!" or after it. We initialize the EventDispatcher in the 
class using it:
dispatcher = new EventDispatcher;

and then attach events like this: 
dispatcher.dispatch("postHello");

The last step is to register callbacks to this event:
dispatcher.addListener("postHello", delegate(Event e, string 
eventName, EventDispatcher dispatcher) {
	writeln("Bye!");
});


Everything together:

import caraus.eventdispatcher.dispatcher;
import caraus.eventdispatcher.event;
import std.functional;
import std.stdio;

class HelloWorld
{
	EventDispatcher dispatcher;

	this()
	{
		dispatcher = new EventDispatcher;
	}

	void hello()
	{
		writeln("Hello world!");
		dispatcher.dispatch("postHello");
	}
}

void main()
{
	auto helloWorld = new HelloWorld;

	helloWorld.dispatcher.addListener("postHello", delegate(Event e, 
string eventName, EventDispatcher dispatcher) {
		writeln("Bye!");
	});

	helloWorld.hello();
}


Now you should get:
Hello world!
Bye!


Why not just extend the HelloWorld class and override the 
hello()? Imagine you write an apllication that should support 
plugins. And two independent plugins extend the HelloWorld. One 
plugin would conflict with the another. EventDispatcher make it 
possible to register the events that can be used by application 
plugins.

Note: If someone wonder about the whole web framework I 
mentioned. In the last week I looked a lot into the vibe.d and I 
moved to its core for handling the requests instead of my own 
CGI-handling. I'm currently working on implementing SCGI based on 
vibe.d IO. And I already have a simple web page of a customer 
running on it (ok, it is a single page website, but it is already 
something :))

Enjoy. Or like people say on this forum: Destroy.
Mar 10 2016
next sibling parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Thursday, 10 March 2016 at 18:08:15 UTC, Eugene Wissner wrote:
 In the last week I looked a lot into the vibe.d and I moved to 
 its core for handling the requests instead of my own 
 CGI-handling. I'm currently working on implementing SCGI based 
 on vibe.d IO
I haven't used vibe.d myself but I did write CGI and SCGI (and fastcgi with the help of a C lib, and an embedded http server) in my cgi.d file: https://github.com/adamdruppe/arsd/blob/master/cgi.d some dox: http://dpldocs.info/experimental-docs/arsd.cgi.html It is written in a traditional manner - no vibe, no fibers, no async. This makes a lot of things easier but it isn't as sexy.
Mar 10 2016
parent Eugene Wissner <belka caraus.de> writes:
On Thursday, 10 March 2016 at 18:15:21 UTC, Adam D. Ruppe wrote:
 On Thursday, 10 March 2016 at 18:08:15 UTC, Eugene Wissner 
 wrote:


 I haven't used vibe.d myself but I did write CGI and SCGI (and 
 fastcgi with the help of a C lib, and an embedded http server) 
 in my cgi.d file:

 https://github.com/adamdruppe/arsd/blob/master/cgi.d

 some dox:
 http://dpldocs.info/experimental-docs/arsd.cgi.html


 It is written in a traditional manner - no vibe, no fibers, no 
 async. This makes a lot of things easier but it isn't as sexy.
Yes, I'm aware of your code, Adam. I'm using it for reference and looking if I don't how to implement something better. Thank you for this work!
Mar 10 2016
prev sibling parent reply Kagamin <spam here.lot> writes:
On Thursday, 10 March 2016 at 18:08:15 UTC, Eugene Wissner wrote:
 Why not just extend the HelloWorld class and override the 
 hello()? Imagine you write an apllication that should support 
 plugins. And two independent plugins extend the HelloWorld. One 
 plugin would conflict with the another. EventDispatcher make it 
 possible to register the events that can be used by application 
 plugins.
How about something like MEF?
Mar 16 2016
parent Eugene Wissner <belka caraus.de> writes:
On Wednesday, 16 March 2016 at 15:14:57 UTC, Kagamin wrote:
 On Thursday, 10 March 2016 at 18:08:15 UTC, Eugene Wissner 
 wrote:
 Why not just extend the HelloWorld class and override the 
 hello()? Imagine you write an apllication that should support 
 plugins. And two independent plugins extend the HelloWorld. 
 One plugin would conflict with the another. EventDispatcher 
 make it possible to register the events that can be used by 
 application plugins.
How about something like MEF?
I didn't know about MEF before, I've just read an article about it, so correct me if I'm wrong. I think that MEF and such event dispatcher aren't comparable. Event dispatching is one of the principles how to extend the application. MEF as Wikipeda states "aims to solve the runtime extensibility problem". The important word is "runtime". So it is a higher level, it is about binding different parts of application at runtime. (As I understand it). Now Symfony, I'm inspired by, has a thing called Bundles. Bundles are just application plugins. And event dispatching can be used inside this bundles aswell. And it is the level where something like MEF would be really great. I think it should be really done, because it would make it possible for example to write closed source plugins for open source applications (it is very common in ecommerce, for example online shops, even for PHP, where you can decode your plugins with something like ioncube). Another area, where it could be used, is routing (already because plugins should be able to add routes to the application at runtime). So concepts like MEF are anyway something very useful for compiled applications/languages and I'll have to find a way to implement it on some stage. Thanks for mentioning it.
Mar 20 2016