Farfetch / kafkaflow

Apache Kafka .NET Framework to create applications simple to use and extend.
https://farfetch.github.io/kafkaflow/
MIT License
638 stars 114 forks source link

[Feature Request]: Message Handlers with constructor args that need setting via factory method #571

Open kevin-mcmanus opened 3 months ago

kevin-mcmanus commented 3 months ago

Is your request related to a problem you have?

I have a generic message handler e.g. public class MyMessageHandler<T> : IMessageHandler<T>.

MyMessageHandler<T> has a constructor with some parameters. e.g. public MyMessageHandler(MyOptions options)

If we register MyOptions in the DI container, all instances of a MyMessageHandler<T> for differing types T will get the same MyOptions injected.

It would be good to enable MyMessageHandler<Tx> to be injected with a different set of options to MyMessageHandler<Ty>.

Describe the solution you'd like

Open to suggestions. Perhaps something like:

.AddMiddlewares(middlewares => middlewares
    .AddTypedHandlers(handler =>
    {
        handler.AddHandler<MyMessageHandler<Tx>>(dependencyResolver=> new MyMessageHandler<Tx>(dependencyResolver.Resolve<MyOptionsX>()));
        handler.AddHandler<MyMessageHandler<Ty>>(dependencyResolver => new MyMessageHandler<Ty>(new MyOptionsY()));
    })
)

Are you able to help bring it to life and contribute with a Pull Request?

No

Additional context

No response

joelfoliveira commented 3 months ago

Hi,

Currently, there is no way to do this. Nevertheless, if your use case is dependent on this you can always delegate the object instance resolution during the middleware invocation (although not ideal). Something like this:

public class MyMessageHandler<T> : IMessageHandler<T> where T : class
{
    private readonly IDependencyResolver _resolver;

    public MyMessageHandler(IDependencyResolver resolver)
    {
        _resolver = resolver;
    }

    public Task Handle(IMessageContext context, T message)
    {
        var options = message is Tx ?  _resolver.Resolve<MyOptions>() : new MyOptions();

        return Task.CompletedTask;
    }
}