How can I solve the "cannot implicitly convert error [type] to [interface]" problem when an interface has multiple common parameters?
I have the following interfaces:
public interface IQueryHandler<in TQuery, out TResult> where TResult : class
where TQuery : IQuery<TResult>
{
TResult Handle(TQuery query);
}
public interface IQuery<TResult> // Doesn't require anything special, just used to guarantee that IQueryHandlers get the right parameters.
{
}
It is intended to be used IQueryHandlers
, which will take in IQuery<TResult>
, which defines a query that returns an object of type TResult
. The method then IQueryHandler
Handle
returns TResult
.
I have an interface implemented in a class DataQueryHandlers
:
public class DataQueryHandlers : IQueryHandler<GetDataById, SomeData>
{
private IDataSource source;
public DataQueryHandlers(IDataSource source)
{
this.source = source
}
public SomeData Handle(GetDataById query)
{
// Get the data here and return SomeData object
}
}
where SomeData
is the data object, and GetDataById
-IQuery<SomeData>
However, when I try to instantiate a specific instance:
private IQueryHandler<IQuery<SomeData>, SomeData> dataQueryHandlers;
private IDataSource source;
source = new DataSource(); // some data provider
dataQueryHandlers = new DataQueryHandlers(datasource); // This line won't compile
I am getting compiler error:
There is no way to implicitly convert the type
DataQueryHandlers
toIQueryHandler<IQuery<SomeData>, SomeData>
. Explicit conversion exists (are you missing a role?)
I'm sure this is a covariant / contravariant problem, but I can't see where the mismatch is. Is there a problem with my inline modifiers? Is this what I am trying to do wrong in some way? I missed some obvious fish hair scenario "here?
source to share
You must change your derived class to a generic class so that it can do this. Change it like this:
public class DataQueryHandlers<in TQuery, out TResult> : IQueryHandler<TQuery, TResult> where TResult : class where TQuery : IQuery<TResult>
{
private IDataSource source;
public DataQueryHandlers(IDataSource source)
{
this.source = source
}
public TResult Handle(TQuery query)
{
// Get the data here and return TResult object
}
}
You can find more details about Generic Classes on MSDN
source to share