如何为所有类型编写linq扩展方法?

时间:2015-02-14 16:45:46

标签: c# .net linq linq-extensions

我想写这个方法:

public static IQueryable<TSource> CutTo<TSource>(this IQueryable<TSource> source, Func<int> func)
{
    int index = func();
    // here I can write something for all types or switch all
    // the types and write code for every type
}

为所有TSource类型编写此代码的最简单方法是什么?

编辑: Black Bear写道,这已经适用于所有类型,但事实并非如此。 Mono这样写道:

public static IQueryable<TSource> Where<TSource> (this IQueryable<TSource> source, Expression<Func<TSource, bool>> predicate)
{
    Check.SourceAndPredicate (source, predicate);

    return source.Provider.CreateQuery<TSource> (
        StaticCall (
            MakeGeneric (MethodBase.GetCurrentMethod (), typeof (TSource)),
            source.Expression,
            Expression.Quote (predicate)));
}

1 个答案:

答案 0 :(得分:1)

第一个解决方案(清洁一个)

仅适用于实现特定界面的类型

创建界面IHaveId

public interface IHaveId
{
    int Id { get; set; }
}

然后每个具有Id属性的模型都应该实现IHaveId。实施例

public class Post : IHaveId
{
    int Id { get; set; }
    string Title { get; set; }
    string Content { get; set; }
}

然后编写CutTo方法,如:

public static IQueryable<T> CutTo<T>(this IQueryable<T> source, Func<int> func)
    where T: IHaveId
{
    int index = func();
    return source.Where(x => x.Id == index);
}

我们的想法是,IHaveId的每个实现都会有int属性Id,然后您可以限制CutTo方法仅适用于IHaveId的实现并使用他们的Id属性。

第二种解决方案(丑陋)

适用于保留实体框架约定以命名主键的任何类型

  1. 使用typeof(TSource)上的反射来查找名为Idtypeof(TSource).Name + "Id"
  2. 的属性
  3. 再次使用反射构建Expression<Func<TSource, int>>并将其应用于IQueryable<T> source Where子句。