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