使用接口和泛型约束进行类型推断

7
我正在构建一个通用的查询调度程序。其思想如下:
- 一个泛型接口IQuery代表一个查询对象 - 一个具体的查询类具有一些getter和setter(实现了IQuery) - 一个泛型接口IQueryHandler,具有一个单独的方法,该方法接收TQuery(对TQuery有一个约束:TQuery: IQuery),并返回TReturnType - 实现IQueryHandler的具体处理程序,接收一个具体的ConcreteQuery并返回一个TQuery - 一个QueryDispatcher,它有一个单独的方法,该方法接收一个查询并返回结果。具体的类将从DI容器中查找正确的处理程序。
问题是当我在QueryDispatcher上调用Fetch方法时,我无法得到类型推断。有没有什么办法可以获得类型推断,或者这只是C#的限制?
理论上,它应该知道类型参数是什么,因为它接收一个TQuery的参数,而TQuery的约束是一个IQuery。
以下是代码:
class ConcreteClass    // This is the class of which I want to query objects
{
}

查询接口 + 具体查询类

interface IQuery<T>
{
}

public class ConcreteQuery : IQuery<ConcreteClass>
{
}

查询处理程序接口 + 具体的查询处理程序

interface IQueryHandler<TReturnType, TQuery> where TQuery : IQuery<TReturnType>
{
    TReturnType Fetch(TQuery query);
}

class ConcreteQueryHandler : IQueryHandler<ConcreteClass, ConcreteQuery>
{
    ConcreteClass Fetch(ConcreteQuery query)
    {
    }
}

查询调度程序(使用 DI 容器解析正确的处理程序)。
class QueryDispatcher
{
    TReturnType Fetch<TReturnType, TQuery>(TQuery query) 
        where TQuery : IQuery<TReturnType>
    {
        return myDIcontainer.Get<IQueryHandler<T, TQuery>>().Fetch(query);
    }
}

现在当我像这样使用QueryDispatcher时,会出现错误:
var queryDispatcher = new QueryDispatcher();
var c = queryDispatcher.Fetch(new ConcreteQuery());

当我提供类型参数时,一切正常运作:
var c = queryDispatcher.Fetch<ConcreteClass, ConcreteQuery>(new ConcreteQuery());

不要认为你有其他选择,因为它现在无法解决TReturnType。 - li-raz
问题是“为什么不呢?”这是C#的限制吗? - Kenneth
@Kenneth 如果你将 var 改为实际类型,会有帮助吗? - Yair Nevet
不,我也尝试过了,虽然这似乎没有什么区别。 - Kenneth
1个回答

1
你需要的是两级类型推断,但编译器无法完成。
你可能需要重新考虑查询分派程序。将其视为接受一个 IQuery<TReturnType> 并返回一个 TReturnType 的东西。
尝试将查询分派程序更改为:
class QueryDispatcher
{
    public TReturnType Fetch<TReturnType>(IQuery<TReturnType> query) 
    {
        return myDIcontainer
            .Get<IQueryHandler<TReturnType, IQuery<TReturnType>>>()
            .Fetch(query);
    }
}

但是理论上来说,编译器应该能够做到这一点,只是C#编译器不够智能,对吧?像那样改变查询分派程序的问题在于我无法为不同的IQuery解析不同的查询处理程序。 - Kenneth

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接