【发布时间】:2015-08-21 09:42:06
【问题描述】:
我已搜索并找到与我的问题相关的类似帖子,但似乎没有任何问题可以解决我的问题。
我是 C# 的新手,这是我第一次尝试构建表达式树。 (请放轻松;-)
我正在尝试创建一个表达式树,一旦编译,它将过滤一组数据的值。
这是我的表达方式:
private static Expression<Func<TItem, bool>> CreateFilterExpression<TItem>(string propertyName, string expressionType, dynamic filterValue)
{
if (param == null)
{
param = Expression.Parameter(typeof(TItem), "item");
}
MemberExpression member = GetMemberExpression<TItem>(propertyName);
//When we call our method, we need to evaluate on the same type
//we convert the filter value to the type of the property we are evaluating on
dynamic convertedValue = Convert.ChangeType(filterValue, member.Type);
MethodInfo method = member.Type.GetMethod(expressionType, new[] { member.Type });
ConstantExpression constantValue = Expression.Constant(convertedValue, member.Type);
Expression containsMethodExp;
if (expressionType == "NotEqual")
{
method = member.Type.GetMethod("Equals", new[] { member.Type });
}
if (member.Type.ToString().ToLower() == "system.string")
{
//We need to compare the lower case of property and value
MethodCallExpression propertyValueToLowerCase = Expression.Call(member, typeof(string).GetMethod("ToLower", System.Type.EmptyTypes));
MethodCallExpression filterValueToLowerCase = Expression.Call(constantValue, typeof(string).GetMethod("ToLower", System.Type.EmptyTypes));
containsMethodExp = Expression.Call(propertyValueToLowerCase, method, filterValueToLowerCase);
}
else if (member.Type.ToString().ToLower() == "system.datetime")
{
//we need to compare only the dates
MemberExpression dateOnlyProperty = Expression.Property(member, "Date");
containsMethodExp = Expression.Call(dateOnlyProperty, method, constantValue);
}
else
{
containsMethodExp = Expression.Call(member, method, constantValue);
}
if (expressionType == "NotEqual")
{
containsMethodExp = Expression.Not(containsMethodExp);
}
return Expression.Lambda<Func<TItem, bool>>(containsMethodExp, param);
}
private static MemberExpression GetMemberExpression<TItem>(string propertyName)
{
if (param == null)
{
param = Expression.Parameter(typeof(TItem), "item");
}
MemberExpression member = null;
//Check if we have a nested property
if (propertyName.Contains('.'))
{
Expression nestedProperty = param;
string[] properies = propertyName.Split('.');
int zeroIndex = properies.Count() - 1;
for (int i = 0; i <= zeroIndex; i++)
{
if (i < zeroIndex)
{
nestedProperty = Expression.PropertyOrField(nestedProperty, properies[i]);
}
else
{
member = Expression.Property(nestedProperty, properies[i]);
}
}
}
else
{
member = Expression.Property(param, propertyName);
}
return member;
}
示例用法如下:
var lambda = CreateFilterExpression<T>("Some.Nested.Object", "Equals", "Some value");
var compiled = lambda.Compile();
gridData = gridData.Where(compiled);
我尝试最终绑定到网格的数据示例如下所示:
public class Some : BaseClass
{
public decimal NumberAvailable { get; set; }
public DateTime EffectiveDate { get; set; }
public Batch Batch { get; set; }
public decimal Price { get; set; }
public decimal Limit { get; set; }
public NestedClass Nested { get; set; }
public int? CompanyId { get; set; }
public decimal Amount { get; set; }
}
public class NestedClass : BaseClass
{
public int RequestId { get; set; }
public string Code { get; set; }
public string Company { get; set; }
public string Reference { get; set; }
}
当我们在一个对象上有空值时出现问题,例如“Some.Nested = null”,然后尝试将“Reference”转换为小写。这里:
MethodCallExpression propertyValueToLowerCase = Expression.Call(member, typeof(string).GetMethod("ToLower", System.Type.EmptyTypes));
这是调试器中的结果:
如何检查嵌套对象上的空值,如果为空则返回空字符串?
我希望我能很好地解释我的问题。提前谢谢!
【问题讨论】:
-
您可以在表达式中添加 if 语句,并在尝试获取属性之前检查当前属性不为空
-
谢谢 Grundy,也许我理解错了,但是对于任何数量的嵌套对象来说,这需要是动态的?
-
你能提供
GetMemberExpression吗? -
当然,已经编辑了我的问题并添加了 GetMemberExpression 方法
-
有许多对 param 的引用 - 没有在任何地方声明。只是一个静态私有成员?
标签: c# lambda expression