简体   繁体   English

使用接口和通用约束键入推断

[英]Type inference with interfaces and generic constraints

I'm building a generic query dispatcher. 我正在构建一个通用的查询调度程序。 The idea is as follows: 这个想法如下:

  • A generic interface IQuery<T> that represents a query object 通用接口IQuery<T> ,表示查询对象
  • A concrete query class has some getters and setters (implementing IQuery<T> ) 具体的查询类有一些getter和setter(实现IQuery<T>
  • A generic interface IQueryHandler<TReturnType, TQuery> with a single method that receives a TQuery (with a constraint on TQuery: IQuery<TReturnType> ) and returns a TReturnType 通用接口IQueryHandler<TReturnType, TQuery>带有一个接收TQuery的方法(对TQuery: IQuery<TReturnType>有约束TQuery: IQuery<TReturnType> )并返回TReturnType
  • Concrete handlers implementing IQueryHandler that receive a concrete ConcreteQuery and return a TQuery 实现IQueryHandler具体处理程序,它接收具体的ConcreteQuery并返回一个TQuery
  • A QueryDispatcher that has a single method that receives a Query and returns a result. 一个QueryDispatcher ,它有一个接收Query并返回结果的方法。 The concrete class will look up the correct handler from a DI container. 具体类将从DI容器中查找正确的处理程序。

The problem is that I don't get type inference when I call the Fetch method on the QueryDispatcher . 问题是当我在QueryDispatcher上调用Fetch方法时,我没有得到类型推断。 Is there anything I can do to get type inference or is this just a limitation of c#? 有什么我可以做的类型推断或这只是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 . 理论上它应该知道类型参数是什么,因为它接收到TQuery的参数,该参数具有作为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 QueryHandler接口+具体的查询处理程序

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) QueryDispatcher(使用DI容器来解析正确的处理程序)

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: 现在,当我像这样使用QueryDispatcher时,我收到一个错误:

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 . 将其视为采用IQuery<TReturnType>并返回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);
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM