Skip to content

Commit 571a79d

Browse files
committed
2 parents c35ed5e + 7fa91c5 commit 571a79d

File tree

1 file changed

+117
-92
lines changed

1 file changed

+117
-92
lines changed

README.md

Lines changed: 117 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,18 @@
55
A 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
1422
You 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.
3749
public 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+
160180
private readonly IMessageDelegator _messageDelegator;
161181

182+
public ProductController(IMessageDelegator messageDelegator)
183+
{
184+
_messageDelegator = messageDelegator;
185+
}
186+
162187
[HttpPost]
163188
public async Task<IActionResult> RegisterProduct([FromBody]RegisterProductCommandDto model)
164189
{

0 commit comments

Comments
 (0)