A lightweight in-process, delegate-based message handling library.
| Branch | Status | 
|---|---|
| Master | |
| Dev | 
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!
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.
You can simply clone this repository, build the source, reference the output dll, and code away!
The library has also been published as a Nuget package:
To install Nuget package:
- Open command prompt
 - Go to project directory
 - Add the package to the project:
dotnet add package Xer.Delegator
 - Restore the packages:
dotnet restore
 
The samples follows the CQRS pattern so you will see commands, events, etc.
// Startup.cs
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
    ...
    // Register message handler resolver to the container. 
    // This is resolved by the MessageDelegator.
    services.AddSingleton<IMessageHandlerResolver>((serviceProvider) =>
    {
        // Commands can only have one handler so use SingleMessageHandlerRegistration.
        var commandHandlerRegistration = new SingleMessageHandlerRegistration();
        
        // Register command handlers to the single message handler registration. 
        // ActivateProductCommand
        commandHandlerRegistration.Register<RegisterProductCommand>((message, cancellationToken) =>
        {
            // You can also manually instantiate if that's how you roll.
            var handler = serviceProvider.GetRequiredService<RegisterProductCommandHandler>();
            return handler.HandleRegisterProductCommandAsync(message, cancellationToken);
        });
        // ActivateProductCommand
        commandHandlerRegistration.Register<ActivateProductCommand>((message, cancellationToken) =>
        {
            // You can also manually instantiate if that's how you roll.
            var handler = serviceProvider.GetRequiredService<ActivateProductCommandHandler>();
            return handler.HandleActivateProductCommandAsync(message, cancellationToken);
        });
        // DeactivateProductCommand
        commandHandlerRegistration.Register<DeactivateProductCommand>((message, cancellationToken) =>
        {
            // You can also manually instantiate if that's how you roll.
            var handler = serviceProvider.GetRequiredService<DeactivateProductCommandHandler>();
            return handler.HandleDeactivateProductCommandAsync(message, cancellationToken);
        });
        return commandHandlerRegistration.BuildMessageHandlerResolver();
    });
    
    // Register message delegator to the container. 
    // This can be simply be: services.AddSingleton<IMessageDelegator, MessageDelegator>(), 
    // but I wanted to clearly show that MessageDelegator depends on IMessageHandlerResolver.
    services.AddSingleton<IMessageDelegator, MessageDelegator>((serviceProvider) =>
        // Get the registered instance of IMessageHandlerResolver shown above.
        new MessageDelegator(serviceProvider.GetRequiredService<IMessageHandlerResolver>())
    );
    ...
}// Startup.cs
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
    ...
    // Register message handler resolver to the container. 
    // This is resolved by the MessageDelegator.
    services.AddSingleton<IMessageHandlerResolver>((serviceProvider) =>
    {
        // Events can have multiple handlers so use MultiMessageHandlerRegistration.
        var eventHandlerRegistration = new MultiMessageHandlerRegistration();
        
        // Register event handlers to the message handler registration. 
        
        // ProductRegisteredEvent
        eventHandlerRegistration.Register<ProductRegisteredEvent>((message, cancellationToken) =>
        {
            // You can also manually instantiate if that's how you roll.
            var handler = serviceProvider.GetRequiredService<ProductDomainEventsHandler>();
            return handler.HandleProductRegisteredEventAsync(message, cancellationToken);
        });
        // ProductActivatedEvent
        eventHandlerRegistration.Register<ProductActivatedEvent>((message, cancellationToken) =>
        {
            // You can also manually instantiate if that's how you roll.
            var handler = serviceProvider.GetRequiredService<ProductDomainEventsHandler>();
            return handler.HandleProductActivatedEventAsync(message, cancellationToken);
        });
        // ProductDeactivatedEvent
        eventHandlerRegistration.Register<ProductDeactivatedEvent>((message, cancellationToken) =>
        {
            // You can also manually instantiate if that's how you roll.
            var handler = serviceProvider.GetRequiredService<ProductDomainEventsHandler>();
            return handler.HandleProductDeactivatedEventAsync(message, cancellationToken);
        });
        return eventHandlerRegistration.BuildMessageHandlerResolver();
    });
    
    // Register message delegator to the container. 
    // This can be simply be: services.AddSingleton<IMessageDelegator, MessageDelegator>(), 
    // but I wanted to clearly show that MessageDelegator depends on IMessageHandlerResolver.
    services.AddSingleton<IMessageDelegator, MessageDelegator>((serviceProvider) =>
        // Get the registered instance of IMessageHandlerResolver shown above.
        new MessageDelegator(serviceProvider.GetRequiredService<IMessageHandlerResolver>())
    );
    ...
}All messages can be delegated to one or more message handlers through the MessageDelegator's SendAsync API.
// ProductController.cs
private readonly IMessageDelegator _messageDelegator;
public ProductController(IMessageDelegator messageDelegator)
{
    _messageDelegator = messageDelegator;
}
[HttpPost]
public async Task<IActionResult> RegisterProduct([FromBody]RegisterProductCommandDto model)
{
    // Convert DTO to domain command.
    RegisterProductCommand command = model.ToDomainCommand();
    // Send command message to handler.
    await _messageDelegator.SendAsync(command);
    return Ok();
}