【问题标题】:No generic method 'ThenBy'没有通用方法“ThenBy”
【发布时间】:2019-03-21 14:56:45
【问题描述】:

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

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”与提供的类型参数和参数兼容。如果方法是非泛型的,则不应提供类型参数。

【问题讨论】:

  • 不确定这是否是您的问题的原因,但您不应该使用System.Linq.IOrderedQueryable 作为扩展方法的this 参数吗?
  • ThenBy是System.Linq.Queryable上的扩展方法
  • 另外,该类型是泛型类型,我认为您应该尝试将Call 您的表达式放在IOrderedQueryable&lt;TEntity&gt; 上,而不是简单的IOrderedQueryable
  • 请注意,如果TEntity 没有Id 属性,这将在运行时失败。我的偏好是为所有具有Id 属性的实体提供一个接口(例如IHasId)并在此处使用通用约束。这样您就可以完全避免表达式并获得编译时安全。
  • 我现在没有建议了:/。我记得尝试通过反射调用扩展方法,与泛型混合,有点棘手......

标签: c# .net-core


【解决方案1】:

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);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-10-14
    • 1970-01-01
    • 2022-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-10
    相关资源
    最近更新 更多