I'm building a generic query dispatcher. The idea is as follows:
IQuery<T>
that represents a query objectIQuery<T>
)IQueryHandler<TReturnType, TQuery>
with a single method that receives a TQuery (with a constraint on TQuery: IQuery<TReturnType>
) and returns a TReturnType
IQueryHandler
that receive a concrete ConcreteQuery
and return a TQueryQueryDispatcher
that has a single method that receives a Query and returns a result. The concrete class will look up the correct handler from a DI container.The problem is that I don't get type inference when I call the Fetch
method on the QueryDispatcher
. Is there anything I can do to get type inference or is this just a limitation of c#?
In theory it should know what the type arguments are since it receives a parameter of TQuery
which has a constraint on being an IQuery<TReturnType
.
This is the code:
class ConcreteClass // This is the class of which I want to query objects
{
}
Query interface + concrete query class
interface IQuery<T>
{
}
public class ConcreteQuery : IQuery<ConcreteClass>
{
}
QueryHandler interface + concrete Query handler
interface IQueryHandler<TReturnType, TQuery> where TQuery : IQuery<TReturnType>
{
TReturnType Fetch(TQuery query);
}
class ConcreteQueryHandler : IQueryHandler<ConcreteClass, ConcreteQuery>
{
ConcreteClass Fetch(ConcreteQuery query)
{
}
}
QueryDispatcher (uses a DI container to resolve the correct handler)
class QueryDispatcher
{
TReturnType Fetch<TReturnType, TQuery>(TQuery query)
where TQuery : IQuery<TReturnType>
{
return myDIcontainer.Get<IQueryHandler<T, TQuery>>().Fetch(query);
}
}
Now when I use the QueryDispatcher like this I get an error:
var queryDispatcher = new QueryDispatcher();
var c = queryDispatcher.Fetch(new ConcreteQuery());
When I provide the type arguments everything works correctly:
var c = queryDispatcher.Fetch<ConcreteClass, ConcreteQuery>(new ConcreteQuery());
What you want is a two level type inference and the compiler won't do it.
You might want to rethink your query dispatcher. Think of it as something that takes an IQuery<TReturnType>
and returns a TReturnType
.
Try changing your query dispatcher to:
class QueryDispatcher
{
public TReturnType Fetch<TReturnType>(IQuery<TReturnType> query)
{
return myDIcontainer
.Get<IQueryHandler<TReturnType, IQuery<TReturnType>>>()
.Fetch(query);
}
}
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