同一上下文中的任意表达式错误:静态方法需要空实例

Arbitrary expression error in same context: Static method requires null instance

我有这个错误:

System.ArgumentException: Static method requires null instance, non-static method requires non-null instance. Parameter name: method

但是在一个地方升起,在另一个地方,在同样的场景下却没有。例如在这种用法中,一切正常:

    public async Task<ValueServiceResult<PagedEnumerable<GenreDto>>> List(int page, int pageSize, int? parentCategory = null)
    {

        return await TryCatchAsync(async () =>
        {
            var whereQuery = parentCategory.HasValue
                ? GetExpression<Genre>(g => g.ParentCategoryId == parentCategory.Value)
                : null;
            var items = await Repository.GeneralQueryPaged(page, pageSize, whereQuery,
                c => c.Name);
            var mappedResult = Mapper.Map<IEnumerable<GenreDto>>(items);
            return new ValueServiceResult<PagedEnumerable<GenreDto>>(new PagedEnumerable<GenreDto>(mappedResult, items.Total, pageSize));
        });
    }

在另一种用法中,它引发了异常:

    public async Task<ValueServiceResult<PagedEnumerable<ArtistDto>>> List(int page, int pageSize, string filter)
    {
        return await TryCatchAsync(async () =>
        {
            if (!string.IsNullOrEmpty(filter))
                filter = filter.Trim().ToLower();
            var whereQuery = !string.IsNullOrEmpty(filter)
                ? GetExpression<Artist>(a => true) /*a.Name.ToLower().Contains(filter)*/
                : null;

            var items = await Repository.GeneralQueryPaged(page, pageSize, whereQuery, c => c.Name);
            var mappedResult = Mapper.Map<IEnumerable<ArtistDto>>(items);
            return new ValueServiceResult<PagedEnumerable<ArtistDto>>(new PagedEnumerable<ArtistDto>(mappedResult, items.Total, pageSize));
        });
    }

GetExpression 调用中引发异常。这是父 class 中的静态方法。这是它的实现方式:

    public static Expression<Func<TEntity, bool>> GetExpression<TEntity> (Func<TEntity, bool> funct)
    {
        return Expression.Lambda<Func<TEntity, bool>>(Expression.Call(funct.Method));
    } 

我只是不明白,怎么可能在一种用法中出现此错误,而在另一种用法中却没有。我在这里错过了什么?

不要使用 Expression.Call,它仅用于调用实际方法。

使用Expression.Invoke调用委托。

Call 可能在某些地方起作用但在其他地方不起作用的原因有很多 - 最有可能的是,起作用的那种有一个闭包,而那些不起作用的......没有。不过,我仍然希望一切都在运行时中断,因为您永远不会将正确的参数传递给 Expression.Call - 您需要传递 lambda 参数(在闭包情况下,闭包实例)。

请注意,如果您使用此辅助方法与 Entity Framework 之类的对象进行交互,它很可能无论如何都无法工作 - 在 C# 中,方法不会自动引用,因此 EF 只能看到方法调用 - 它看不到方法内部。但是,如果你只是使用它稍后调用(使用例如 Compile().Invoke()),你没问题。

代码示例:

public static Expression<Func<TEntity, bool>> Wrap<TEntity>(Func<TEntity, bool> func)
{
    var entity = Expression.Parameter(typeof(TEntity));
    return 
        Expression.Lambda<Func<TEntity, bool>>
        (
            Expression.Invoke(Expression.Constant(func), entity), 
            entity
        );
}