【发布时间】:2015-10-20 08:26:59
【问题描述】:
问题
我有一个扩展方法,它扩展 IEnumerable<T> 并采用 Expression 导航到本身必须是 IEnumerable 的属性。
/// <summary>
/// Identify a child collection to search on
/// </summary>
/// <param name="source">source data on which to search</param>
/// <param name="property">Enumerable properties to search.</param>
public static IEnumerable<TSource> Search<TSource, TProperty>(
this IEnumerable<TSource> source,
Expression<Func<TSource, IEnumerable<TProperty>> property)
{
// Do stuff...
}
当子属性定义为IEnumerable<T>时,上面的效果很好,可以如下调用:
var result = shops.Search(s => s.ProductEnumerable);
然而如果子属性是ICollection<T>、IList<T>或任何实现IEnumerable<T>的东西,它目前找不到这个方法
另一个关键点是我希望能够在不明确定义类型的情况下使用该方法。
var result = shops.Search(s => s.ProductList);
//NOT
var result = shops.Search<Shop, Product>(s => s.ProductList);
我尝试过的
尝试 1
我想我可以创建一个新的泛型 (TCollection) 并限制 TCollection 是 IEnumerable<TProperty> 的位置。
public static IEnumerable<TSource> Search<TSource, TCollection, TProperty>(
this IEnumerable<TSource> source,
Expression<Func<TSource, TCollection>> property)
where TCollection : IEnumerable<TProperty>
这失败了,因为代码无法再找到该方法。
尝试 2
然后我认为我可以将整个第二个参数设为泛型并对其进行正确的约束。
public static IEnumerable<TSource> Search<TSource, TCollection, TProperty>(
this IEnumerable<TSource> source,
TCollection property)
where TCollection : Expression<Func<TSource, IEnumerable<TProperty>>
这也失败并出现以下错误:
不能使用密封类
Expression<TDelegate>作为类型参数约束。
有没有办法实现我想要的,或者我只需要为所有实现 IEnumerable 的接口创建重载???
提前感谢您花时间阅读这篇冗长的说明
【问题讨论】:
-
Search方法应该做什么? -
当您说
however it currently does not find this method if the child property is...时,您能详细说明您的意思吗?正如下面的答案所示,目前尚不清楚您实际遇到了什么问题。 -
好问题....再次查看代码后,当我将属性更改为
ICollection时,我收到一条错误消息,告诉我问题在于它正在尝试使用不同的Search的过载。我会更新我的问题。谢谢 -
ICollection不继承IEnumerable<T>- 对于 非泛型 类型,您肯定需要不同的重载。 -
ICollection<T>确实 - https://msdn.microsoft.com/en-us/library/92t2ye13(v=vs.110).aspx。这里的 cmets 和答案已经意识到我真正的问题,所以我会尝试自己解决这个问题,但是如果我无法解决问题,我很可能会创建一个新问题
标签: c# generics lambda expression extension-methods