同一上下文中的任意表达式错误:静态方法需要空实例
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
);
}
我有这个错误:
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
);
}