使用接口和通用约束进行类型推断 [英] Type inference with interfaces and generic constraints

查看:112
本文介绍了使用接口和通用约束进行类型推断的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在构建一个通用查询调度器。这个想法如下:


  • 通用接口 IQuery< T> 查询对象
  • 具体的查询类有一些getter和setter(实现 IQuery< T>
  • 使用接收TQuery的单个方法(在上具有约束条件)的TQuery:IQuery< TReturnType>的通用接口 IQueryHandler< TReturnType,TQuery> ; )并返回一个 TReturnType

  • 实现 IQueryHandler 接收具体的 ConcreteQuery 并返回一个TQuery

  • A QueryDispatcher 有一个接收查询并返回结果的单一方法。具体类将从DI容器中查找正确的处理程序。



问题是我没有得到类型推断在 QueryDispatcher 上调用 Fetch 方法。有什么我可以做的类型推断,或者这只是一个限制的C#?

理论上它应该知道类型参数是什么,因为它接收一个参数 TQuery ,它有一个约束是一个 IQuery< TReturnType



这是代码:

  class ConcreteClass //这是我想要查询对象的类
{
}

查询接口+具体查询类

 接口IQuery< T> 
{
}

公共类ConcreteQuery:IQuery< ConcreteClass>
{
}

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

  interface IQueryHandler< TReturnType,TQuery>其中TQuery:IQuery< TReturnType> 
{
TReturnType Fetch(TQuery查询);
}

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



QueryDispatcher(使用DI容器来解析正确的处理程序)

pre $ class QueryDispatcher
{
TReturnType Fetch< TReturnType,TQuery>(TQuery查询)
其中TQuery:IQuery< TReturnType>
{
return myDIcontainer.Get< IQueryHandler< T,TQuery>>()。Fetch(query);






$ b现在当我使用这个QueryDispatcher时,错误:


  var queryDispatcher = new QueryDispatcher(); 
var c = queryDispatcher.Fetch(new ConcreteQuery());

当我提供类型参数时,一切正常:

  var c = queryDispatcher.Fetch< ConcreteClass,ConcreteQuery>(new ConcreteQuery()); 


解决方案

您需要的是两级类型推理,编译器不会这样做。



您可能想重新考虑您的查询调度程序。把它看作是一个需要 IQuery< TReturnType> 并且返回一个 TReturnType



尝试将您的查询调度程序更改为:

  class QueryDispatcher 
{
public TReturnType Fetch< TReturnType>(IQuery< TReturnType> query)
{
return myDIcontainer
.Get< IQueryHandler< TReturnType,IQuery< TReturnType>>>()
。取(查询);
}
}


I'm building a generic query dispatcher. The idea is as follows:

  • A generic interface IQuery<T> that represents a query object
  • A concrete query class has some getters and setters (implementing 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
  • Concrete handlers implementing IQueryHandler that receive a concrete ConcreteQuery and return a TQuery
  • A QueryDispatcher 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);
    }
}

这篇关于使用接口和通用约束进行类型推断的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆