C# 如何使用MethodCallExpression/lambda在树中从ConditionalExpression.if返回?
我试图让表达式树有条件地计算为字符串 以下是我迄今为止的代码:C# 如何使用MethodCallExpression/lambda在树中从ConditionalExpression.if返回?,c#,linq,expression-trees,C#,Linq,Expression Trees,我试图让表达式树有条件地计算为字符串 以下是我迄今为止的代码: IQueryable<Category> myCategories = DataUtil.Categories.AsQueryable(); ParameterExpression categoryParameterExpression = Expression.Parameter(typeof (Category), "category"); MemberExpression categoryNameMemberEx
IQueryable<Category> myCategories = DataUtil.Categories.AsQueryable();
ParameterExpression categoryParameterExpression = Expression.Parameter(typeof (Category), "category");
MemberExpression categoryNameMemberExpression = Expression.PropertyOrField(categoryParameterExpression, "CategoryName");
MemberExpression categoryNameLengthExpression = Expression.Property(categoryNameMemberExpression, typeof (string).GetProperty("Length"));
ConstantExpression constantLengthExpression = Expression.Constant(10, typeof (int));
BinaryExpression greaterThanLengthExpression = Expression.GreaterThan(categoryNameLengthExpression, constantLengthExpression);
var getNameInCapsMethod = typeof (Category).GetMethod("GetNameInCaps", BindingFlags.Instance | BindingFlags.Public);
MethodCallExpression getNameInCapsExpression = Expression.Call(categoryParameterExpression, getNameInCapsMethod, categoryNameMemberExpression);
ConditionalExpression ifGreaterThanLengthGetUpperNameExpression = Expression.IfThen(greaterThanLengthExpression, getNameInCapsExpression);
// I need something between the lambda and the ConditionalExpression to ensure that the void type is not returned?
var ifGreaterThanLengthGetUpperNameLambdaExpression = Expression.Lambda<Func<Category, string>>(ifGreaterThanLengthGetUpperNameExpression, new ParameterExpression[] { categoryParameterExpression });
foreach (var category in myCategories)
{
var upperName = ifGreaterThanLengthUpperLambda(category);
System.Windows.MessageBox.Show(upperName);
}
IQueryable myCategories=DataUtil.Categories.AsQueryable();
ParameterExpression categoryParameterExpression=Expression.Parameter(类别的类型),“类别”);
MemberExpression CategoryNameExpression=Expression.PropertyOrField(categoryParameterExpression,“CategoryName”);
MemberExpression CategoryNameLengtheExpression=Expression.Property(categoryNameMemberExpression,typeof(string).GetProperty(“长度”);
ConstantExpression constantLengthExpression=表达式常数(10,typeof(int));
BinaryExpression greaterthangtheexpression=表达式。GreaterThan(类别名称表达式,常量表达式);
var getNameInCapsMethod=typeof(Category).GetMethod(“GetNameInCaps”,BindingFlags.Instance | BindingFlags.Public);
MethodCallExpression getNameInCapsExpression=Expression.Call(categoryParameterExpression、getNameInCapsMethod、categoryNameMemberExpression);
如果大于长度GetUpperNameExpression=表达式,则条件表达式为。如果大于长度表达式,则条件表达式为getNameInCapsExpression;
//我需要lambda和ConditionalExpression之间的一些东西来确保不返回void类型?
var ifGreaterThanLengthGetUpperNameLambdaExpression=Expression.Lambda(ifGreaterThanLengthGetUpperNameExpression,新参数表达式[]{categoryParameterExpression});
foreach(myCategories中的var类别)
{
var upperName=ifGreaterThanLengthUpperLambda(类别);
System.Windows.MessageBox.Show(大写);
}
以下是运行时发生的ArgumentException:
中发生类型为“System.ArgumentException”的未处理异常
System.Core.dll
其他信息:“System.Void”类型的表达式不能为空
用于返回类型“System.String”
我发现ConditionalExpression返回的是“IfFalse”条件的void类型
以下是我的表达式树可视化工具的屏幕截图:
我只需要字符串值。我意识到在ConditionalExpression类型上有一个表达式。IfThenElse,但我不确定在Else表达式中放什么。(如果可能的话,我不想只是传回一个空字符串。)有没有办法确保只有在前面的二进制表达式的计算结果为true时才计算条件?不管怎样,我该如何解决这个问题呢?更全面地表达您真正想要实现的目标可能会有所帮助(基本上,您想要的表达式树的C#等价物是什么样子的)。目前,您的表达式树大致如下所示:
Func<Category, string> f = (category) => {
if (category.CategoryName.Length > 10) {
category.GetNameInCaps(category.CategoryName);
}
};
Func f=(类别)=>{
如果(category.CategoryName.Length>10){
category.GetNameInCaps(category.CategoryName);
}
};
但是,C#编译器不会编译它,因为您没有在任何代码路径上返回字符串,所以表达式树没有按照您希望的方式编译也就不足为奇了。至少有两个问题:
表达式.Condition,而不是表达式.IfThen
。这将为您提供相当于语法,这是一个可以用作lambda返回值的表达式。作为一条语句,if(…){}
块始终具有您发现的类型void
(即使添加了else
,也是如此)
- 选择一些要返回的默认无意义值(例如
或null
),或“”
- 抛出异常