将表达式<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;