Convert Expression<Func<TDocument, object>> to E
本文关键字:gt lt to object Func Expression Convert TDocument | 更新日期: 2023-09-27 18:14:03
我有以下类型为Expression<Func<TDocument, object>>
的表达式
x => x.Name
现在,我在编译时不知道x.Name
的类型,但我现在知道它在运行时,因为它存储在Type
中。
我如何将我的表达式转换为类型Expression<Func<TDocument, TOutput>>
,其中TOutput
是Type
,在编译时不知道?
您只需要将原始表达式的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);
附录
注意,对于结构返回类型,最终表达式可能看起来像这样:
(TDocument d) => (int)(object)d.ID;