我有以下表达式Expression<Func<TDocument, object>>
x => x.Name
现在,我在编译时并不知道x.Name
的类型,但我现在在运行时因为它存储在Type
中。
如何将我的表达式转换为Expression<Func<TDocument, TOutput>>
类型TOutput
为Type
且在编译时不知道?
答案 0 :(得分:3)
您只需将原始表达式的Body
包装在Convert
表达式中,然后重建lambda。如果我可以使用泛型,我就会这样做:
Expression<Func<TInput, TReturn>> ConvertReturnValue<TInput, TReturn>(
Expression<Func<TInput, object>> inputExpression)
{
Expression convertedExpressionBody = Expression.Convert(
inputExpression.Body, typeof(TReturn)
);
return Expression.Lambda<Func<TInput, TReturn>>(
convertedExpressionBody, inputExpression.Parameters
);
}
用法:
Expression<Func<TDocument, object>> inputExpression = d => d.Name;
Expression<Func<TDocument, string>> convertedExpression
= ConvertReturnValue<TDocument, string>(inputExpression);
// Test.
TDocument doc = new TDocument { Name = "Zzz" };
string name = convertedExpression.Compile().Invoke(doc);
Assert.Equal("Zzz", name);
没有泛型
如果由于在编译时不知道返回类型而无法使用泛型,Expression.Lambda
实际上提供了非泛型重载,您可以像这样使用:
Expression ConvertReturnValue<TInput>(Expression<Func<TInput, object>> inputExpression, Type returnType)
{
Expression convertedExpressionBody = Expression.Convert(inputExpression.Body, returnType);
return Expression.Lambda(convertedExpressionBody, inputExpression.Parameters);
}
上述内容仍会返回Expression<Func<TInput, TReturn>>
(向上转换为非通用Expression
)。如果您需要,可以稍后再转发它:
Expression<Func<TDocument, object>> inputExpression = d => d.Name;
Expression<Func<TDocument, string>> convertedExpression
= (Expression<Func<TDocument, string>>)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;