2014-02-22 39 views
6

我正在構建一個通用查詢調度程序。這個想法是如下:使用接口和通用約束進行類型推斷

  • 通用接口IQuery<T>表示一個查詢對象
  • 一個具體的查詢類有一些getter和setter(實施IQuery<T>
  • 通用接口IQueryHandler<TReturnType, TQuery>與接收一個單一的方法一個TQuery的(與TQuery: IQuery<TReturnType>約束),並返回收到具體ConcreteQuery並返回一個的TQuery TReturnType
  • 混凝土處理器實現IQueryHandler
  • A QueryDispatcher它有一個接收查詢並返回結果的單一方法。具體的類將從DI容器中查找正確的處理程序。

問題是,當我撥打QueryDispatcher上的Fetch方法時,我沒有得到類型推斷。有什麼我可以做的類型推斷,或者這只是一個限制的C#?

理論上它應該知道類型參數是什麼,因爲它接收的參數是TQuery,它的參數是IQuery<TReturnType

這是代碼:

class ConcreteClass // This is the class of which I want to query objects 
{ 
} 

查詢接口+混凝土查詢類

interface IQuery<T> 
{ 
} 

public class ConcreteQuery : IQuery<ConcreteClass> 
{ 
} 

QueryHandler接口+混凝土查詢處理程序

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

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

QueryDispatcher(使用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()); 
+0

不認爲你有其他的選擇,因爲它現在不能如何解決TReturnType –

+0

的問題是這是c#的限制嗎? – Kenneth

+0

@Kenneth如果你把'var'改成真正的類型,它有幫助嗎? –

回答

0

你想要的是一個兩級類型推理,編譯器不會這樣做。

您可能想要重新考慮您的查詢調度程序。把它看作是需要IQuery<TReturnType>並返回TReturnType的東西。

試着改變你的查詢調度員:「爲什麼不呢?」

class QueryDispatcher 
{ 
    public TReturnType Fetch<TReturnType>(IQuery<TReturnType> query) 
    { 
     return myDIcontainer 
      .Get<IQueryHandler<TReturnType, IQuery<TReturnType>>>() 
      .Fetch(query); 
    } 
} 
+0

但我說得對,理論上編譯器應該可以做到,但是C#編譯器不夠聰明,對嗎?像這樣改變查詢調度程序的問題是,我不能爲不同的IQuery解析不同的查詢處理程序 – Kenneth