如何在扩展方法中使用泛型类型成员?

时间:2016-12-07 14:16:32

标签: c# linq generics reflection extension-methods

我开始使用这种扩展方法很有趣,但现在我发现自己陷入其中,

实际上我想创建一个扩展方法来扩展LINQ,方法将如下所示:

books.In(b => b.Id, 1,2,3,4,5);

它会在第二个params[]

中返回ID范围的图书

也可以这样做:

books.In(b => b.Title, "t1","t2","t3","t4","t5");

我想出的是这种方法(我今天才知道表达式树!):

 public static List<TEntity> In<TEntity, TMember>(this List<TEntity> list,
            Expression<Func<TEntity, TMember>> identifier, params TMember[] keys)
        {
            Type t = typeof(TEntity); //How to use reflection here?

            List<TEntity> myList = list.Where(m => keys.Contains(m.));
            return myList;
        }

我的问题是如何访问通用类成员:m.Id表达式m.Titleidentifier? 我可以使用反射来实现这一目标吗?

1 个答案:

答案 0 :(得分:2)

这应该做:

public static IEnumerable<TEnitity> In<TEnitity, TMember>(
    this IEnumerable<TEnitity> source, 
    Func<TEnitity, TMember> projector, IEnumerable<TMember> validCases)
{
    var validSet = new HashSet<TMember>(validCases);
    return source.Where(s => validSet.Contains(projector(s)));
}

或者,为了遵守您提出的签名:

public static IEnumerable<TEntity> In<TEntity, TMember>(
    this IEnumerable<TEntity> source,
    Func<TEntity, TMember> projector, params TMember[] validCases)
{
    var validSet = new HashSet<TMember>(validCases);
    return source.Where(s => validSet.Contains(projector(s)));
}

关于我为什么要返回IEnumerable<T>而不是List<T>,推理是廉价的推广;如果消费者想要返回一个列表,那么他只需要调用ToList,但为什么让他付出贪婪地枚举的费用,如果他只想在枚举中迭代一次?记住,LINQ是 lazy ,利用它并​​尽可能少地工作。

为什么我接受IEnumerable<T>作为论据,又是廉价的概括;为什么只接受清单?为什么不是数组,队列,堆栈,集合,迭代器块,哈希集等?