I have multiple dependency injected handlers and want to find the appropriate one to solve a task. I finally ended up finding the corresponding handler (in class HandlerResolver
) but i can't return the Handler
as method result.
Interfaces:
public interface IMessage
{
}
public interface IHandler<TRoot, in TMessage> where TRoot : class
{
public abstract TRoot Apply(TRoot root, TMessage message);
}
// Marker interface to register/resolve dependency injected handlers
public interface IHandler
{
}
Handlers:
public class Handler1: IHandler<MyRoot, Message1>, IHandler
{
public MyRoot Apply(MyRoot aggregateRoot, Message1 message)
{
...
return aggregateRoot;
}
}
public class Handler2: IHandler<MyRoot, Message2>, IHandler
{
public MyRoot Apply(MyRoot aggregateRoot, Message2 message)
{
...
return aggregateRoot;
}
}
Messages:
public class Message1 : ICaseMessage
{
...
}
public class Message2 : ICaseMessage
{
...
}
DI Registrations:
services.AddScoped<IResolver, HandlerResolver>();
services.AddScoped<IHandler, Handler1>();
services.AddScoped<IHandler, Handler2>();
Resolve Handler:
public class HandlerResolver : IResolver
{
private IEnumerable<IHandler> Handlers { get; } // DI injected handlers
public HandlerResolver(IEnumerable<IHandler> handlers)
{
Handlers = handlers;
}
public IHandler<TRoot, TMessage> GetHandler<TRoot, TMessage>(TRoot root, TMessage message)
where TRoot : class
where TMessage : class,
{
var concreteRootType = root.GetType();
var concreteMessageType = message.GetType();
var handlerOrNull = this.Handlers.FirstOrDefault(p =>
{
var genericArguments = p.GetType().GetInterfaces().First().GenericTypeArguments;
return genericArguments[0] == concreteAggregateType &&
genericArguments[1] == concreteMessageType;
});
if (handlerOrNull == null)
{
throw new NotImplementedException($"No Handler Found");
}
else
{
return handlerOrNull as IHandler<TRoot, TMessage>;
}
}
}
return handlerOrNull as IHandler<TRoot, TMessage>;
This will always return null
. I think this is due to the parsing. It seems trying to parse it into a IHandler<TRoot, IMessage>
which for some reason doesn't work.
I have also tried this solution How to determine if a type implements a specific generic interface type which doesn't work if the generic type is not known.