55A lightweight in-process message handling library without the boilerplates!
66
77# Table of contents
8+ * [ What is it?] ( #what-is-it )
89* [ Installation] ( #installation )
910* [ Getting Started] ( #getting-started )
10- * [ ASPNET Core Startup Configuration] ( #aspnet-core-startup-configuration )
11- * [ Message Sending] ( #message-sending )
11+ * [ Message Handler Registration] ( #message-handler-registration )
12+ * [ Single Message Handler] ( #single-message-handler )
13+ * [ Multiple Message Handlers] ( #multiple-message-handlers )
14+ * [ Delegating Messages] ( #delegating-messages )
15+
16+ ## What is it?
17+ This library is developed with a goal to help developers speed up the development of applications by minimizing boilerplates in the code. No message marker interfaces, no message handler interfaces, no pipelines, etc - just define a message class, hook up delegates, and you're good to go!
18+
19+ This makes the library suitable for building prototypes/proof of concept applications, but at the same time, also serve as a lightweight base for your own messaging infrastructure.
1220
1321## Installation
1422You can simply clone this repository, build the source, reference the output dll, and code away!
@@ -29,10 +37,14 @@ To install Nuget package:
2937 ```
3038
3139## Getting Started
40+ The samples follows the CQRS pattern so you will see commands , events , etc .
3241
33- ### ASPNET Core Startup Configuration
42+ ### Message Handler Registration
43+ #### Single Message Handler
3444
3545```csharp
46+ // Startup.cs
47+
3648// This method gets called by the runtime. Use this method to add services to the container.
3749public void ConfigureServices (IServiceCollection services )
3850{
@@ -43,122 +55,135 @@ public void ConfigureServices(IServiceCollection services)
4355 {
4456 // Register command handlers to the message handler registration.
4557 // Commands can only have one handler so use SingleMessageHandlerRegistration.
46- SingleMessageHandlerRegistration commandHandlerRegistration = RegisterCommandHandlers ( serviceProvider );
58+ var commandHandlerRegistration = new SingleMessageHandlerRegistration ( );
4759
48- // Register event handlers to the message handler registration.
49- // Events can have multiple handlers so use MultiMessageHandlerRegistration.
50- MultiMessageHandlerRegistration eventHandlerRegistration = RegisterEventHandlers (serviceProvider );
51-
52- // Combine command handlers and event handlers.
53- return new CompositeMessageHandlerResolver (new IMessageHandlerResolver []
60+ // RegisterProductCommand
61+ commandHandlerRegistration .Register <RegisterProductCommand >((message , ct ) =>
5462 {
55- commandHandlerRegistration . BuildMessageHandlerResolver (),
56- eventHandlerRegistration . BuildMessageHandlerResolver ()
63+ var handler = serviceProvider . GetRequiredService < RegisterProductCommandHandler >();
64+ return handler . HandleRegisterProductCommandAsync ( message , ct );
5765 });
58- });
5966
60- // Message delegator.
61- services .AddSingleton <IMessageDelegator , MessageDelegator >();
62- .. .
63- }
64-
65- // Register all command handlers
66- private static SingleMessageHandlerRegistration RegisterCommandHandlers (IServiceProvider serviceProvider )
67- {
68- // Register command handlers to the message handler registration.
69- // Commands can only have one handler so use SingleMessageHandlerRegistration.
70- var commandHandlerRegistration = new SingleMessageHandlerRegistration ();
67+ // ActivateProductCommand
68+ commandHandlerRegistration .Register <ActivateProductCommand >((message , ct ) =>
69+ {
70+ var handler = serviceProvider .GetRequiredService <ActivateProductCommandHandler >();
71+ return handler .HandleActivateProductCommandAsync (message , ct );
72+ });
7173
72- // ActivateProductCommand
73- commandHandlerRegistration .Register <RegisterProductCommand >((message , ct ) =>
74- {
75- var handler = serviceProvider .GetRequiredService <RegisterProductCommandHandler >();
76- return handler .HandleRegisterProductCommandAsync (message , ct );
77- });
74+ // DeactivateProductCommand
75+ commandHandlerRegistration .Register <DeactivateProductCommand >((message , ct ) =>
76+ {
77+ var handler = serviceProvider .GetRequiredService <DeactivateProductCommandHandler >();
78+ return handler .HandleDeactivateProductCommandAsync (message , ct );
79+ });
7880
79- // ActivateProductCommand
80- commandHandlerRegistration .Register <ActivateProductCommand >((message , ct ) =>
81- {
82- var handler = serviceProvider .GetRequiredService <ActivateProductCommandHandler >();
83- return handler .HandleActivateProductCommandAsync (message , ct );
81+ return commandHandlerRegistration .BuildMessageHandlerResolver ();
8482 });
83+
84+ // Register message delegator to the container.
85+ // This can be simply be: services.AddSingleton<IMessageDelegator, MessageDelegator>(),
86+ // but I wanted to clearly show that MessageDelegator depends on IMessageHandlerResolver.
87+ services .AddSingleton <IMessageDelegator , MessageDelegator >((serviceProvider ) =>
88+ // Get the registered instance of IMessageHandlerResolver shown above.
89+ new MessageDelegator (serviceProvider .GetRequiredService <IMessageHandlerResolver >())
90+ );
91+ .. .
92+ }
93+ ```
8594
86- // DeactivateProductCommand
87- commandHandlerRegistration .Register <DeactivateProductCommand >((message , ct ) =>
88- {
89- var handler = serviceProvider .GetRequiredService <DeactivateProductCommandHandler >();
90- return handler .HandleDeactivateProductCommandAsync (message , ct );
91- });
95+ #### Multiple Message Handlers
9296
93- return commandHandlerRegistration ;
94- }
97+ ``` csharp
98+ // Startup.cs
9599
96- // Register event handlers
97- private static MultiMessageHandlerRegistration RegisterEventHandlers ( IServiceProvider serviceProvider )
100+ // This method gets called by the runtime. Use this method to add services to the container.
101+ public void ConfigureServices ( IServiceCollection services )
98102{
99- // Register event handlers to the message handler registration.
100- // Events can have multiple handlers so use MultiMessageHandlerRegistration.
101- var eventHandlerRegistration = new MultiMessageHandlerRegistration ();
102-
103- // In the sample, all events are published as IDomainEvent by the PublishingRepository,
104- // so register event handlers for IDomainEvent and check if domain event can be handled.
105-
106- // ProductRegisteredEvent
107- eventHandlerRegistration .Register <IDomainEvent >((message , ct ) =>
103+ .. .
104+ // Register message handler resolver to the container.
105+ // This is resolved by the MessageDelegator.
106+ services .AddSingleton <IMessageHandlerResolver >((serviceProvider ) =>
108107 {
109- ProductRegisteredEvent domainEvent = message as ProductRegisteredEvent ;
110- if (domainEvent != null )
111- {
112- // Handle only if domain event is a ProductRegisteredEvent.
113- var handler = serviceProvider .GetRequiredService <ProductDomainEventsHandler >();
114- return handler .HandleProductRegisteredEventAsync (domainEvent , ct );
115- }
108+ // Register event handlers to the message handler registration.
109+ // Events can have multiple handlers so use MultiMessageHandlerRegistration.
110+ var eventHandlerRegistration = new MultiMessageHandlerRegistration ();
116111
117- // Do nothing.
118- return Task .CompletedTask ;
119- });
112+ // In the sample, all events are published as IDomainEvent by the PublishingRepository,
113+ // so register event handlers for IDomainEvent and check if domain event can be handled.
120114
121- // ProductActivatedEvent
122- eventHandlerRegistration .Register <IDomainEvent >((message , ct ) =>
123- {
124- ProductActivatedEvent domainEvent = message as ProductActivatedEvent ;
125- if (domainEvent != null )
115+ // ProductRegisteredEvent
116+ eventHandlerRegistration .Register <IDomainEvent >((message , ct ) =>
126117 {
127- // Handle only if domain event is a ProductActivatedEvent.
128- var handler = serviceProvider .GetRequiredService <ProductDomainEventsHandler >();
129- return handler .HandleProductActivatedEventAsync (domainEvent , ct );
130- }
118+ ProductRegisteredEvent domainEvent = message as ProductRegisteredEvent ;
119+ if (domainEvent != null )
120+ {
121+ // Handle only if domain event is a ProductRegisteredEvent.
122+ var handler = serviceProvider .GetRequiredService <ProductDomainEventsHandler >();
123+ return handler .HandleProductRegisteredEventAsync (domainEvent , ct );
124+ }
125+
126+ // Do nothing.
127+ return Task .CompletedTask ;
128+ });
131129
132- // Do nothing.
133- return Task .CompletedTask ;
134- });
130+ // ProductActivatedEvent
131+ eventHandlerRegistration .Register <IDomainEvent >((message , ct ) =>
132+ {
133+ ProductActivatedEvent domainEvent = message as ProductActivatedEvent ;
134+ if (domainEvent != null )
135+ {
136+ // Handle only if domain event is a ProductActivatedEvent.
137+ var handler = serviceProvider .GetRequiredService <ProductDomainEventsHandler >();
138+ return handler .HandleProductActivatedEventAsync (domainEvent , ct );
139+ }
140+
141+ // Do nothing.
142+ return Task .CompletedTask ;
143+ });
135144
136- // ProductDeactivatedEvent
137- eventHandlerRegistration .Register <IDomainEvent >((message , ct ) =>
138- {
139- ProductDeactivatedEvent domainEvent = message as ProductDeactivatedEvent ;
140- if (domainEvent != null )
145+ // ProductDeactivatedEvent
146+ eventHandlerRegistration .Register <IDomainEvent >((message , ct ) =>
141147 {
142- // Handle only if domain event is a ProductDeactivatedEvent.
143- var handler = serviceProvider .GetRequiredService <ProductDomainEventsHandler >();
144- return handler .HandleProductDeactivatedEventAsync (domainEvent , ct );
145- }
148+ ProductDeactivatedEvent domainEvent = message as ProductDeactivatedEvent ;
149+ if (domainEvent != null )
150+ {
151+ // Handle only if domain event is a ProductDeactivatedEvent.
152+ var handler = serviceProvider .GetRequiredService <ProductDomainEventsHandler >();
153+ return handler .HandleProductDeactivatedEventAsync (domainEvent , ct );
154+ }
155+
156+ // Do nothing.
157+ return Task .CompletedTask ;
158+ });
146159
147- // Do nothing.
148- return Task .CompletedTask ;
160+ return eventHandlerRegistration .BuildMessageHandlerResolver ();
149161 });
150-
151- return eventHandlerRegistration ;
162+
163+ // Register message delegator to the container.
164+ // This can be simply be: services.AddSingleton<IMessageDelegator, MessageDelegator>(),
165+ // but I wanted to clearly show that MessageDelegator depends on IMessageHandlerResolver.
166+ services .AddSingleton <IMessageDelegator , MessageDelegator >((serviceProvider ) =>
167+ // Get the registered instance of IMessageHandlerResolver shown above.
168+ new MessageDelegator (serviceProvider .GetRequiredService <IMessageHandlerResolver >())
169+ );
170+ .. .
152171}
153172```
154173
155- ### Message Sending
156- All messages can be sent to one or more message handlers through the MessageDelegator. SendAsync method .
174+ #### Delegating Messages
175+ All messages can be delegated to one or more message handlers through the MessageDelegator's SendAsync API .
157176
158177``` csharp
159- // Inject in controller contructor.
178+ // ProductController.cs
179+
160180private readonly IMessageDelegator _messageDelegator ;
161181
182+ public ProductController (IMessageDelegator messageDelegator )
183+ {
184+ _messageDelegator = messageDelegator ;
185+ }
186+
162187[HttpPost ]
163188public async Task < IActionResult > RegisterProduct ([FromBody ]RegisterProductCommandDto model )
164189{
0 commit comments