2013-05-30 65 views
1

我有这样的事情:C#泛型方法类型约束对几类

public List<T> GetPageRows<T>(Expression<Func<T, bool>> predicate, List<ColumnSortOrder> sortOrder, int pageSize, int pageNo) where T : Type1, Type2, Type3 
    { 
     var filteredQueryable = GetRowsAndFilter(predicate); 
     var orderedQueryable = GetOrderedQueryable(sortOrder, filteredQueryable); 
     var pagedQueryable = orderedQueryable.Skip((pageNo - 1) * pageSize).Take(pageSize); 
     return pagedQueryable.ToList(); 
    } 

    private IQueryable<Type1> GetRowsAndFilter(Expression<Func<Type1, bool>> predicate) 
    { 
     return GetType1s(predicate); 
    } 

    private IQueryable<Type2> GetRowsAndFilter(Expression<Func<Type2, bool>> predicate) 
    { 
     return GetType2s(predicate); 
    } 

    private IQueryable<Type3> GetRowsAndFilter(Expression<Func<Type3, bool>> predicate) 
    { 
     return GetType3s(predicate); 
    } 

我希望,通过使GetRowsAndFilter()的非通用类特定版本,然后是制约GetPageRows泛型类型参数()分配给这三个类中的一个,编译器能够找出该做什么。

但是where T : Type1, Type2, Type3似乎是非法的。

我该如何解决这个问题?

这个想法是,GetPageRows()中的算法是通用的,并且不依赖于我得到的特定类型的行。只有返回类型和谓词取决于T.

编辑:我试图约束他们的基类型和共同的空接口,但我仍然在var filteredQueryable = GetRowsAndFilter(predicate);中得到一个错误。 “无法解析方法”。它不知道如何选择这些方法的正确版本。我不知道该怎么办。应该可以将实际类型T中的GetPageRows()中的一般算法与不同版本的GetRowsAndFilter()中的每个T的特定不同查询分开。

+0

约束问题可以解决,但不幸的是,这不会解决后续的不可解析的方法调用问题。 –

+0

没办法解决这个问题呢?:( – pinkfloydhomer

+0

我想我可能会有一些东西,我已经修改了我的答案,但不确定它是否可行,并且可能会使代码共享失去很多好处 –

回答

2

尽管您可以使用空接口指定一个约束来绕过多个约束,但这并不能解决您的问题:不能正确解析GetRowsAndFilter

弯曲代码一点后,我想出了这个存根(我改变了切东西出去找它来编译,但你应该能够运用同样的理念,你的代码):

static void Main(string[] args) 
    { 
     var res = GetPageRows<Type1>(GetRowsAndFilter, t => true, null, 0, 0); 
     var res2 = GetPageRows<Type2>(GetRowsAndFilter, t => true, null, 0, 0); 

     Console.ReadLine(); 
    } 

    public static List<T> GetPageRows<T>(Func<Expression<Func<T, bool>>, IEnumerable<T>> getRows, Expression<Func<T, bool>> predicate, List<int> sortOrder, int pageSize, int pageNo) 
    { 
     var filteredQueryable = getRows(predicate); 
     return filteredQueryable.ToList(); 
    } 

    private static IEnumerable<Type1> GetRowsAndFilter(Expression<Func<Type1, bool>> predicate) 
    { 
     return Enumerable.Empty<Type1>(); 
    } 

    private static IEnumerable<Type2> GetRowsAndFilter(Expression<Func<Type2, bool>> predicate) 
    { 
     return Enumerable.Empty<Type2>(); 
    } 

    private static IEnumerable<Type3> GetRowsAndFilter(Expression<Func<Type3, bool>> predicate) 
    { 
     return Enumerable.Empty<Type3>(); 
    } 

您还需要提供方法来调用,否则编译器无法解析它,因为它没有足够的关于T的类型信息,通过提供方法并使其在方法签名中使用相同的泛型类型,编译器至少可以确保方法在谈论相同的T。在呼叫方(GetPageRows<Type1>()),指定类型是剩下要正确解析的驱动程序。

0

明确指定这三种不同的类型在直觉上是错误的:您如何知道,在编译时安全类型,您正在使用哪种类型?定义所有派生的公共基类或它们全部实现的接口,并将泛型参数类型约束为该最小公分母。

+0

这三种类型已经从相同的基类,我也试着让它们实现同一个空接口,问题是,如果我这样做,仍然会在'var filteredQueryable = GetRowsAndFilter(predicate);'中得到错误,似乎无法选择是否有另一种方法可以将GetPageRows中的算法与特定类型T分开,并将每种类型的特定查询分别存放在特定版本的GetRowsAndFilter()中? – pinkfloydhomer

+0

是的,但是您需要在该基础上进行约束类型或接口 - 它不会检测到这三种类型共享一个基础,并自动将该方法限制为---它们,你需要告诉它。 –

+0

我已经这样做了,它仍然失败o 'GetRowsAndFilter(predicate);' – pinkfloydhomer

1

因为在C#中多重继承是不可能的,所以除非Type1,Type2Type3中的最多一个不是接口,否则不能这样做。如果Type1,Type2,Type3中不止一个不是接口,则不可能满足约束条件。另外,这些接口必须以类型约束的顺序排列。

你可以说,等一下,如果Type3 : Type2 : Type1?在这种情况下,我们仍然可以有一个T,它可以满足Type1而不是Type2Type3。所以在这种情况下,我们从编写Type1, Type2, Type3,因为它本身相当于Type3,我们从中得不到什么。

+0

我想你的意思是写“Type1,Type2和Type3中至多一个是_not_接口。”? –

+0

@FredrikMörk:是的。感谢您的更正! – jason