I'm playing with cqs a little bit and I'm trying to implement this in a class library (so there's no IOC, IServiceProvider, etc). Here is some code that I wrote:
public interface IQuery<TResult>
{
}
public interface IQueryHandler<TQuery, TResult> where TQuery : IQuery<TResult>
{
TResult Handle(TQuery query);
}
public class Query : IQuery<bool>
{
public int Value { get; set; }
}
public class QueryHandler : IQueryHandler<Query, bool>
{
public bool Handle(Query query)
{
return query.Value > 0;
}
}
public class Dispatcher
{
private readonly Dictionary<Type, object> handlers = new Dictionary<Type, object>();
public Dispatcher()
{
handlers.Add(typeof(Query), new QueryHandler());
}
public T Dispatch<T>(IQuery<T> query)
{
IQueryHandler<IQuery<T>, T> queryHandler;
if (!this.handlers.TryGetValue(query.GetType(), out object handler) ||
((queryHandler = handler as IQueryHandler<IQuery<T>, T>) == null))
{
throw new Exception();
}
return queryHandler.Handle(query);
}
}
And this si how I am calling my code:
Query query = new Query();
Dispatcher dispatcher = new Dispatcher();
var result = dispatcher.Dispatch(query);
But the problem is that inside the dispatcher, I don't know why the variable handler cannot be casted as IQueryHandler<IQuery<T>,T>. Here is some extra data:

PS: I know how to make this work(with dynamic), but I want to understand why THIS code isn't working.
This is a covariance problem. The real type of handler is QueryHandler, so it is a IQueryHandler<Query, bool>. Of course Query is an IQuery<bool>, but that is the point of covariance.
It is like trying to assign a List<String> to a variable of type List<Object>.
There exists an out keyword that allows you to use the covariance on your IQueryHandler interface as you expect it.
See out for detailed information
EDIT:
As pointed out by Sweeper, you cannot use out on TQuery because it is used as input parameter. The correct solution is to avoid the dependecy of QueryHandler on Query. Isma has shown nicely how it is done.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With