我有一个类代表一个通用过滤器对象
public class Filter
{
public string column { get; set; }
public string operator { get; set; }
public string data { get; set; }
}
LambdaExpression
多亏了这样的代码,我才能进行转换
public LambdaExpression ToExpression( IQueryable query ) {
LambdaExpression toReturn = null;
ParameterExpression parameter = Expression.Parameter( query.ElementType, "p" );
MemberExpression memberAccess = GetMemberExpression( column, parameter );
ConstantExpression filter = Expression.Constant( Convert.ChangeType( data, memberAccess.Type ) );
WhereOperation condition = (WhereOperation)StringEnum.Parse( typeof( WhereOperation ), operator );
LambdaExpression lambda = BuildLambdaExpression( memberAccess, filter, parameter, condition, data );
if ( toReturn == null ) {
toReturn = lambda;
}
return toReturn;
}
根据要求,Filter
成员column
可以包含一种用于查询字段的导航语法,其表达FieldA.FieldB.Description
方式如下:
- 获取从 FieldA 属性返回的类型 T 的值
- 获取T的FieldB返回的类型T1的值
- 获取 T2 的描述返回的类型 T2 的值
结果是一个像这样的 lambda:p.FieldA.FieldB.Description == "data"
我可以将此结果用作Where
任何扩展方法的参数IQueryable
当导航查询的成员之一是Nullable
类型时,问题就出现了。在这种情况下,假设 FieldA 可以为空,正确的 lambda 应该是
p.FieldA != null && p.FieldA.FieldB.Description == "data"
我尝试在MemberExpression
使用类似这样的代码构造对象时实现此检查
MemberExpression memberAccess = null;
foreach ( var property in column.Split( '.' ) ) {
memberAccess = MemberExpression.Property( memberAccess ?? ( p as Expression ), property );
Type memberType = memberAccess.Type;
if ( memberType.IsGenericType &&
memberType.GetGenericTypeDefinition() == typeof( Nullable<> ) ) {
//Create here an expression of type : memberAccess != null
}
}
这适用于原始类型,但不适用于其他对象引用,例如 EFEntityReference
对象实例。我知道我可以简单地在前面添加另一个条件,if
比如
if ( ( memberType.IsGenericType &&
memberType.GetGenericTypeDefinition() == typeof( Nullable<> ) ) ||
memberType.IsClass ) {
}
但在我看来,这似乎太通用了,产生了一个条件太多的 lambda,其中大多数可能没用。
有没有办法更好地区分可空引用?