2016-11-24 117 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); 

当你调用这个方法,你必须提供所有的类型参数,或者没有(如果它们可以被推断的话)。就是那样子。