2016-11-24 112 views
2

我想創建一個方法,該方法基於給定泛型類型從數據庫返回數據。如何約束一般方法的嵌套泛型類型

接口:(這個定義編譯)

public interface IOrderPosition<TOrder, TArticle, TOrderPosition> 
    where TOrder : IOrder 
    where TArtile : IArticle 
    where TOrderPosition : IOrderPosition<TOrder, TArticle, TOrderPosition> 
{ 
    long? id { get; set; } 
    TOrder order { get; set; } 
    TArtile article { get; set; } 
    List<TOrderPosition> subPositions { get; set; } 
} 

一種可能的具體實施:(這個定義編譯)

public class OrderPosition : IOrderPosition<Order, Article, OrderPosition> 
{ 
    public long? id { get; set; } 
    public Order order { get; set; } 
    public Article article { get; set; } 
    public List<OrderPosition> subPositions { get; set; } 
} 

試圖寫入基於所述的通用方法接口:(該定義不能編譯)

public List<TOrderPosition> GetOrderPositionOfOrder<TOrderPosition>(long? id) 
    where TOrder : IOrder 
    where TArticle : IArticle 
    where TOrderPosition : IOrderPosition<TOrder, TArticle, TOrderPosition> 
{ 
    .. 
} 

錯誤:

'DataSourceOrder.GetOrderPositionOfOrder<TOrderPosition>()' does not define type parameter 'TOrder' 
'DataSourceOrder.GetOrderPositionOfOrder<TOrderPosition>()' does not define type parameter 'TArticle' 
The type or namespace name 'TOrder' could not be found (are you missing a using directive or an assembly reference?) 
The type or namespace name 'TArticle' could not be found (are you missing a using directive or an assembly reference?) 

要這樣來使用:

List<OrderPosition> positions = GetOrderPositionOfOrder<OrderPosition>(5); 
List<TransferOrderPosition> transferPositions = GetOrderPositionOfOrder<TransferOrderPosition>(5); 

問:

爲什麼會爲接口編譯,但不是用於該方法?

我預計工作或兩者都失敗。我認爲編譯可以從TOrderPosition給出的類型推斷出TOrder和TArticle的類型,它定義了文章和訂單的具體類型。

我想知道爲什麼會發生這種情況,以及如何以及如何解決問題,而無需明確指定所有類型。

+3

但是你沒有在你的方法中定義TOrder和TArticle泛型參數,否則它會編譯。並且對於類,你指定了所有三個(TOrder,TArtile,TOrderPosition) – Evk

+0

@Evk在回答這個問題時看起來很明顯,這是不可能的,我只是希望編譯器能以某種方式推斷出類型' OrderPosition',因爲我想避免必須列出所有類型(實際上多於3個) – Holly

回答

3

爲什麼這個編譯的界面,但不是該方法?

嗯,你是在IOrderPosition接口聲明TOrderTArticle但不是在GetOrderPositionOfOrder方法。

您需要聲明的方法聲明這些通用參數:

public List<TOrderPosition> GetOrderPositionOfOrder<TOrder, TArticle, TOrderPosition>(long? id) 
    where TOrder : IOrder 
    where TArticle : IArticle 
    where TOrderPosition : IOrderPosition<TOrder, TArticle, TOrderPosition> 
{ 
    ... 
} 

,並調用它是這樣的:

var list = GetOrderPositionOfOrder<Order, Article, OrderPosition>(5); 

但是,如果你想打電話GetOrderPositionOfOrder,如:

var list = GetOrderPositionOfOrder<OrderPosition>(5); 

您可以使TOrderTArticleIOrderPosition協:

interface IOrderPosition<out TOrder, out TArticle, TOrderPosition> 
    where TOrder : IOrder 
    where TArticle : IArticle 
    where TOrderPosition : IOrderPosition<TOrder, TArticle, TOrderPosition> 
{ 
    long? id { get; set; } 
    TOrder order { get; } 
    TArticle Article { get; } 
    List<TOrderPosition> subPositions { get; set; } 
} 

注意OrderArticle必須是唯一的消氣屬性(但這些屬性在OrderPosition可以set訪問)。

而且方法:

public List<TOrderPosition> GetOrderPositionOfOrder<TOrderPosition>(long? id) 
    where TOrderPosition : IOrderPosition<IOrder, IArticle, TOrderPosition> 
{ 
    ... 
} 

這樣做可以讓喜歡GetOrderPositionOfOrder<OrderPosition>(5)的電話。

+0

謝謝您展示了一種我不需要明確聲明所有類型的方法,因爲這會消除整個解決方案的優雅,可悲的是,它可能不會幫助我,因爲我需要.Net 3.5 CF,我還需要設置那些值不會讀取它們的方法 – Holly

+0

@Holly:呃,那麼也許你可以創建一個基本接口,比如'IOrderPosition 其中TOrderPosition:IOrderPosition (如果需要,可以使用id和subPositions屬性)並且您的當前接口繼承此接口。然後你可以像這樣聲明方法:'GetOrderPositionOfOrder (long?id)其中TOrderPosition:IOrderPosition ' –

+1

感謝您的建議,我一直在考慮同樣的事情,但我不確定它甚至是值得的第一個麻煩,因爲我需要反映所有類型和演員等現在我讀了嵌套的泛型類型沒有得到推斷(我假設),我甚至嘗試提供OrderPosition具體類型的一個實例作爲參數,希望能夠推斷出所有的類型參數,但那也行不通 - 現在我有點想念JAVA'?擴展ClassName' ;-) – Holly

0

在界面中,將其定義爲通用接受3種類型TOrder, TArticle, TOrderPosition,因此您可以限制這些類型。

您的方法只定義了一種類型,TOrderPosition,編譯器無法推斷出您需要方法定義中的約束where TOrderPosition : IOrderPosition<TOrder, TArticle, TOrderPosition>中的其他類型。

你需要做的是在你爲你的界面以同樣的方式定義你的泛型方法的所有類型:

public List<TOrderPosition> GetOrderPositionOfOrder<TOrder, TArticle, TOrderPosition>(long? id) 
where TOrder : IOrder 
where TArticle : IArticle 
where TOrderPosition : IOrderPosition<TOrder, TArticle, TOrderPosition> 
{ 
.. 
} 
2

在錯誤請看:

「DataSourceOrder .GetOrderPositionOfOrder()」不限定類型參數 'TOrder' 'DataSourceOrder.GetOrderPositionOfOrder()' 不限定類型參數 'TArtile'

您指的是不存在的類型參數。
你應該在方法來定義它們,你定義它們的接口是相同的:這意味着調用方法

public static List<TOrderPosition> GetOrderPositionOfOrder<TOrder, TArticle, TOrderPosition>(long? id) 

會有點醜:

var positions = GetOrderPositionOfOrder<Order, Position, OrderPosition>(5); 
var transferPositions = GetOrderPositionOfOrder<TransferOrder, TransferArticle, TransferOrderPosition>(5); 

當你調用這個方法,你必須提供所有的類型參數,或者沒有(如果它們可以被推斷的話)。就是那樣子。