如何为 Nullable<Int32> 等可空属性创建动态 C# 表达式 func<tentity, bool>
How to make dynamic C# expression func<tentity, bool> for nullable properties like Nullable<Int32>
我在生成用于 EF Core 查询的动态函数时遇到问题。
这是函数生成器
public static Expression<Func<TEntity, bool>> WhereFunc<TEntity>(this string propertyName,
object? propertyValue)
where TEntity : class, IEntity
{
var info = typeof(TEntity).GetProperty(propertyName);
var parameter = Expression.Parameter(typeof(TEntity), $"{nameof(TEntity).Substring(0,
2)}");
var property = Expression.Property(parameter, propertyName);
var value = Expression.Constant(propertyValue);
var clause = Expression.Equal(property, Expression.Constant(propertyValue));
return Expression.Lambda<Func<TEntity, bool>>(clause, parameter);
}
这是所有需要的属性的动态查询生成器
public static IQueryable<TEntity> SetWhere<TEntity, TSearch>(this IEnumerable<TEntity>
entities, IEnumerable<PropertyInfo> fields, TSearch entity)
where TEntity : class, IEntity
where TSearch : class, ISearchEntity
{
var query = entities.AsQueryable();
if (fields != null && fields.Any())
foreach (var item in fields)
query = query.Where(EntityFuncs.WhereFunc<TEntity>(item.Name, item.GetValue(entity)));
return query;
}
这是我使用它的代码:
var query = Entities
.Skip(filter.Total)
.Take(filter.More)
.AsQueryable();
query = query.SetWhere<TEntity, TSearchEntity>(properties, filter.Entity);
对于字符串属性,它可以正常工作。
但在 nullable<int>
属性的示例中,我收到此错误:
The binary operator Equal is not defined for the types 'System.Nullable`1[System.Int32]' and 'System.Int32
您必须显式测试 propertyValue
的类型或 属性 的类型,并相应地调用 Nullable.Equals
。
Nullable.GetUnderlyingType
如果给定类型是 Nullable<>
构造的类型(例如 int?
);否则将 return null
.
public static Expression<Func<TEntity, bool>> WhereFunc<TEntity>(this string propertyName, object? propertyValue)
where TEntity : class, IEntity
{
var info = typeof(TEntity).GetProperty(propertyName);
var parameter = Expression.Parameter(typeof(TEntity), $"{nameof(TEntity).Substring(0, 2)}");
var property = Expression.Property(parameter, propertyName);
var value = Expression.Constant(propertyValue);
var propertyType = info?.PropertyType ?? propertyValue?.GetType();
var underlyingType = propertyType is not null ? Nullable.GetUnderlyingType(propertyType) : null;
Expression clause;
if (underlyingType is not null)
{
var methodOpen = typeof(Nullable).GetMethod(nameof(Nullable.Equals), BindingFlags.Static | BindingFlags.Public);
var method = methodOpen.MakeGenericMethod(underlyingType);
clause = Expression.Call(method, property, Expression.Convert(value, propertyType));
}
else
{
clause = Expression.Equal(property, value);
}
return Expression.Lambda<Func<TEntity, bool>>(clause, parameter);
}
我在生成用于 EF Core 查询的动态函数时遇到问题。
这是函数生成器
public static Expression<Func<TEntity, bool>> WhereFunc<TEntity>(this string propertyName,
object? propertyValue)
where TEntity : class, IEntity
{
var info = typeof(TEntity).GetProperty(propertyName);
var parameter = Expression.Parameter(typeof(TEntity), $"{nameof(TEntity).Substring(0,
2)}");
var property = Expression.Property(parameter, propertyName);
var value = Expression.Constant(propertyValue);
var clause = Expression.Equal(property, Expression.Constant(propertyValue));
return Expression.Lambda<Func<TEntity, bool>>(clause, parameter);
}
这是所有需要的属性的动态查询生成器
public static IQueryable<TEntity> SetWhere<TEntity, TSearch>(this IEnumerable<TEntity>
entities, IEnumerable<PropertyInfo> fields, TSearch entity)
where TEntity : class, IEntity
where TSearch : class, ISearchEntity
{
var query = entities.AsQueryable();
if (fields != null && fields.Any())
foreach (var item in fields)
query = query.Where(EntityFuncs.WhereFunc<TEntity>(item.Name, item.GetValue(entity)));
return query;
}
这是我使用它的代码:
var query = Entities
.Skip(filter.Total)
.Take(filter.More)
.AsQueryable();
query = query.SetWhere<TEntity, TSearchEntity>(properties, filter.Entity);
对于字符串属性,它可以正常工作。
但在 nullable<int>
属性的示例中,我收到此错误:
The binary operator Equal is not defined for the types 'System.Nullable`1[System.Int32]' and 'System.Int32
您必须显式测试 propertyValue
的类型或 属性 的类型,并相应地调用 Nullable.Equals
。
Nullable.GetUnderlyingType
如果给定类型是 Nullable<>
构造的类型(例如 int?
);否则将 return null
.
public static Expression<Func<TEntity, bool>> WhereFunc<TEntity>(this string propertyName, object? propertyValue)
where TEntity : class, IEntity
{
var info = typeof(TEntity).GetProperty(propertyName);
var parameter = Expression.Parameter(typeof(TEntity), $"{nameof(TEntity).Substring(0, 2)}");
var property = Expression.Property(parameter, propertyName);
var value = Expression.Constant(propertyValue);
var propertyType = info?.PropertyType ?? propertyValue?.GetType();
var underlyingType = propertyType is not null ? Nullable.GetUnderlyingType(propertyType) : null;
Expression clause;
if (underlyingType is not null)
{
var methodOpen = typeof(Nullable).GetMethod(nameof(Nullable.Equals), BindingFlags.Static | BindingFlags.Public);
var method = methodOpen.MakeGenericMethod(underlyingType);
clause = Expression.Call(method, property, Expression.Convert(value, propertyType));
}
else
{
clause = Expression.Equal(property, value);
}
return Expression.Lambda<Func<TEntity, bool>>(clause, parameter);
}