没有通用方法“ ThenBy”

时间:2019-03-21 14:56:46

标签: c# .net-core

我正在尝试添加ThenById()方法,该方法将在调用OrderBy()上的IOrderedQueryable之后启动:

public static IOrderedQueryable<TEntity> ThenById<TEntity>(this IQueryable<TEntity> source)
{
    if (source == null)
    {
        throw new ArgumentNullException(nameof(source));
    }

    var command = "ThenBy";
    var thenByProperty = "Id";
    var type = typeof(TEntity);

    if (type.GetProperty(thenByProperty) == null)
    {
        throw new MissingFieldException(nameof(thenByProperty));
    }

    var param = Expression.Parameter(type, "p");

    var property = type.GetProperty(thenByProperty, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);

    var propertyAccess = Expression.MakeMemberAccess(param, property);
    var orderByExpression = Expression.Lambda(propertyAccess, param);

    var resultExpression = Expression.Call(
        typeof(IOrderedQueryable),
        command,
        new Type[] { type, property.PropertyType },
        source.Expression,
        Expression.Quote(orderByExpression));
    return (IOrderedQueryable<TEntity>)source.Provider.CreateQuery<TEntity>(resultExpression);
}

我收到以下错误消息:

  

类型为'System.Linq.IOrderedQueryable'的通用方法'ThenBy'与提供的类型实参和实参不兼容。如果该方法是非泛型的,则不应该提供任何类型的参数。

1 个答案:

答案 0 :(得分:3)

ThenBy扩展方法在System.Linq.Queryable类中,而不在IOrderedQueryable中。您只需要在代码中替换它即可:

public static IOrderedQueryable<TEntity> ThenById<TEntity>(
    this IOrderedQueryable<TEntity> source)
{
    //snip

    var resultExpression = Expression.Call(
        typeof(System.Linq.Queryable),
        command,
        new Type[] { type, property.PropertyType },
        source.Expression,
        Expression.Quote(orderByExpression));
    return (IOrderedQueryable<TEntity>)source.Provider.CreateQuery<TEntity>(resultExpression);
}

请注意,该方法应扩展IOrderedQueryable,而不仅仅是IQueryable

但是,如果TEntity没有Id属性,则此操作将在运行时失败。我的偏好是为所有具有Id属性的实体提供接口,并在此处使用一般约束。这样,您可以完全避免使用表达式,并获得编译时的安全性。例如:

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

public class SomeEntity : IHasId
{
    public int Id { get; set; }
    public string Name { get; set; }
    //etc
}

这简化了您的扩展方法:

public static IOrderedQueryable<TEntity> ThenById<TEntity>(
    this IOrderedQueryable<TEntity> source)
        where TEntity : IHasId
{
    return source.ThenBy(e => e.Id);
}