表达式.如何比较空字段和非空字段
本文关键字:字段 比较 何比较 表达式 | 更新日期: 2023-09-27 18:13:55
我有一个可空的datetime
字段,我必须将string
日期字段转换为可空的日期时间类型(使用Expression
)....我使用了下面的代码:
Expression.Constant(Convert.ChangeType(value, Nullable.GetUnderlyingType(memberAccess.Type)));.
memberAccess(如上所述)是成员表达式类型。(从LinqExtensions.cs)现在在代码中,我使用表达式。相等的方法。
Expression.Equal(memberAccess, filter);
这个在这里失败了,因为成员访问类型是可空的,但是filter。类型不可为空…
即使我尝试使用
将成员访问类型转换为可空类型ConstantExpression test = Expression.Constant(Nullable.GetUnderlyingType(memberAccess.Type)),
类型是Runtime而不是DateTime。
如何使用Expression.Equal
比较可空&不可空字段?是否有任何方法将字符串类型转换为可空的日期时间字段?这两个都能解决我的问题。
Ok…我就是这样做的。
第一次转换类型(string to datetime)
filter = Expression.Constant(
Convert.ChangeType(value, memberAccess.Type.GetGenericArguments()[0]));
然后将该表达式转换为所需的类型
Expression typeFilter = Expression.Convert(filter, memberAccess.Type);
然后使用Expression.Equal(memberAccess, typeFilter)...
(memberAccess is MemberExpression
,它从模型中获取属性类型)
如果您有可空值而不是日期,这就是如何为可空类型创建表达式树的方法,假设您有一个可空字段BoardId,您可以像这样动态地创建表达式树
var nameValue ="BoardId = 111";
public static Expression<Func<T, bool>> BuildWhereExpression<T>(string nameValueQuery ) where T : class
{
Expression<Func<T, bool>> predicate = null;
PropertyInfo prop = null;
var fieldName = nameValueQuery.Split("=")[0];
var fieldValue = nameValueQuery.Split("=")[1];
var properties = typeof(T).GetProperties();
foreach (var property in properties)
{
if (property.Name.ToLower() == fieldName.ToLower())
{
prop = property;
}
}
if (prop != null)
{
var isNullable = prop.PropertyType.IsNullableType();
var parameter = Expression.Parameter(typeof(T), "x");
var member = Expression.Property(parameter, fieldName);
if (isNullable)
{
var filter1 =
Expression.Constant(
Convert.ChangeType(fieldValue, member.Type.GetGenericArguments()[0]));
Expression typeFilter = Expression.Convert(filter1, member.Type);
var body = Expression.Equal(member, typeFilter);
predicate = Expression.Lambda<Func<T, bool>>(body, parameter);
}
else
{
if (prop.PropertyType == typeof(string) && likeOerator.ToLower() == "like")
{
var parameterExp = Expression.Parameter(typeof(T), "type");
var propertyExp = Expression.Property(parameterExp, prop);
MethodInfo method = typeof(string).GetMethod("Contains", new[] { typeof(string) });
var someValue = Expression.Constant(fieldValue, typeof(string));
var containsMethodExp = Expression.Call(propertyExp, method, someValue);
predicate = Expression.Lambda<Func<T, bool>>(containsMethodExp, parameterExp);
}
else
{
var constant = Expression.Constant(Convert.ChangeType(fieldValue, prop.PropertyType));
var body = Expression.Equal(member, constant);
predicate = Expression.Lambda<Func<T, bool>>(body, parameter); `enter code here`
}
}
}
return predicate;
}
1-此解决方案首先检查Nullable值并生成表达式。这就是如何确定类型是否为Nullable。我为此创建了一个扩展方法
public static bool IsNullableType(this Type type)
{
return type.IsGenericType && (type.GetGenericTypeDefinition().Equals(typeof(Nullable<>)));
}
2-第二步是检查类型是否为字符串,然后为字符串创建表达式。
3-第三步是检查值是否为空,然后使用equal
可以传递Type in Expression。常数:
ConstantExpression constant = Expression.Constant(value, member.Type);
BinaryExpression equalExpression = Expression.Equal(member, constant);
您应该使用DateTime.Parse
或更好的DateTime.ParseExact
来将字符串转换为日期。所以,Expression.Call
如果你想在字符串为空的情况下将其转换为空日期,你可以使用Expression.Condition
。
如果你想让结果为空,我相信Expression.Convert
可以做到这一点。
Condition(
Equals(yourStringExpression, null),
Constant(null, typeof(DateTime?)),
Convert(
Call(DateTime.ParseExact, yourStringExpression, ...),
typeof(DateTime?)
)
)