Sylver.HandlerInvoker
is a .NET Core library that provides a mechanism to invoke actions just like ASP.NET Core controllers.
The implementation has been highly inspired by the ASP.NET Core MVC source code. Thank you Microsoft and all developers of ASP.NET Core :-)
Sylver.HandlerInvoker
has been designed to be integrated with the .NET Core generic HostBuilder
, so it can benefit from the built-in dependency injection pattern, configuration and logging.
Handler classes must be tagged with the [Handler]
attribute and their actions (public
methods) with the [HandlerAction]
attribute so the loader can load and store the informations into the handler's cache.
[HandlerAction]
takes on parameter which represents the unique identifier of the action. It can take whatever you want, since it takes an object
.
Handler actions can also have parameters, like primitive values or complex objects.
[Handler]
public class CustomHandler
{
[HandlerAction("FirstHandlerAction")]
public void MyFirstHandlerAction(int index, MyCustomObject customObject)
{
// Do stuff
}
}
Handlers integrate well with the .NET Core HostBuilder. When you create a new application using the HostBuilder
class, simply call the AddHandlers()
method on the ConfigureServices()
method of the HostBuilder
.
static async Task Main()
{
var host = new HostBuilder()
.ConfigureServices((hostContext, services) =>
{
services.AddHandlers();
// TODO: Add IHostedService to run a background service
})
.UseConsoleLifetime()
.Build();
await host.RunAsync();
}
To invoke a handler action, you just need to inject the IHandlerInvoker
interface into your services and call the Invoke()
method with the handler action in first parameter and your handler parameters.
In this example we create a hosted service that will be registered in the
ConfigureServices
of theHostBuilder
.
public class MyService : IHostedService
{
private readonly IHandlerInvoker _handlerInvoker;
public MyService(IHandlerInvoker handlerInvoker)
{
this._handlerInvoker = handlerInvoker;
}
public Task StartAsync(CancellationToken cancellationToken)
{
Console.WriteLine("StartAsync()");
// Invokes the CustomHandler.MyFirstHandlerAction with 10 as first parameter and a new custom object as second parameter.
this._handlerInvoker.Invoke("FirstHandlerAction", 10, new MyCustomObject(42));
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken)
{
Console.WriteLine("StopAsync()");
return Task.CompletedTask;
}
}
When a handler action is called, the invoke informations are cached for future invocations. The cached informations are the following:
- Handler type : Simply the action's parent handler type.
- Handler factory creator : A
Func<object>
that creates a new instance of the handler. - Handler releaser : An
Action<object>
that calls theIDisposable.Dispose()
method of the handler if it implements it. - Handler action executor : A custom object that builds an expression tree and can execute the handler action. The expression tree is built once and then cached to avoid performance issues.
- Thank you to the ASP.NET Core team and contributors for the great code and inspiration. I've learned a lot of things by reading the code. :-)
- Package icon from icons8