将表达式<Func >转换为Expression <Func >
我有以下表达式,其类型为Expression<Func>
x => x.Name
现在,我不知道编译时x.Name
的类型,但我现在它在运行时,因为它存储在一个Type
。
如何将表达式转换为Expression<Func>
Type
,其中TOutput
是一个Type
而在编译时不知道?
您只需要将原始表达式的Body
包装在Convert
表达式中,然后重建lambda。 如果我可以使用generics,我会怎么做:
Expression> ConvertReturnValue( Expression> inputExpression) { Expression convertedExpressionBody = Expression.Convert( inputExpression.Body, typeof(TReturn) ); return Expression.Lambda>( convertedExpressionBody, inputExpression.Parameters ); }
用法:
Expression> inputExpression = d => d.Name; Expression> convertedExpression = ConvertReturnValue(inputExpression); // Test. TDocument doc = new TDocument { Name = "Zzz" }; string name = convertedExpression.Compile().Invoke(doc); Assert.Equal("Zzz", name);
没有generics
如果由于在编译时不知道返回类型而无法使用generics, Expression.Lambda
实际上提供了非generics重载,您可以像这样使用:
Expression ConvertReturnValue(Expression> inputExpression, Type returnType) { Expression convertedExpressionBody = Expression.Convert(inputExpression.Body, returnType); return Expression.Lambda(convertedExpressionBody, inputExpression.Parameters); }
上面仍然返回Expression
(向上转换为非通用Expression
)。 如果您需要,您可以稍后将其转发:
Expression> inputExpression = d => d.Name; Expression> convertedExpression = (Expression>)ConvertReturnValue(inputExpression, typeof(string)); // Test. TDocument doc = new TDocument { Name = "Zzz" }; string name = convertedExpression.Compile().Invoke(doc); Assert.Equal("Zzz", name);
附录
请注意,对于struct返回类型,最终表达式最终可能如下所示:
(TDocument d) => (int)(object)d.ID;