我有以下表达式,类型为表达式< Func< TDocument,object>>
x => x.Name现在,我不知道 x的类型。在编译时命名,但是现在它在运行时,因为它存储在一个类型中。
如何将我的表达式转换为类型表达式&FunC< TDocument,TOutput>> 其中 TOutput 是一个类型,在编译时不知道?
解决方案你只需要在转换表达式中包装原始表达式的 Body ,然后重建lambda。以下是我可以如何使用泛型:
表达式&FunC< TInput,TReturn> ;> ConvertReturnValue< TInput,TReturn>(表达式< Func< TInput,object>> inputExpression) {表达式convertedExpressionBody = Expression.Convert( inputExpression.Body,typeof(TReturn )); 返回Expression.Lambda无泛型
如果您不能使用泛型,因为您在编译时不知道返回类型, Expression.Lambda 实际上提供了非泛型重载,您可以使用它this:
Expression ConvertReturnValue< TInput>(Expression< Func< TInput,object>> inputExpression,类型returnType) { Expression convertedExpressionBody = Expression.Convert(inputExpression.Body,returnType); 返回Expression.Lambda(convertedExpressionBody,inputExpression.Parameters); }上述仍然返回一个表达式&FunC< TInput ,TReturn>> (upcast到非泛型 Expression )。如果需要,您可以稍后下载:
表达式< Func< TDocument,object>> inputExpression = d => d.Name; 表达式< Func< TDocument,string>> convertExpression =(表达式& Func< TDocument,string>>)ConvertReturnValue(inputExpression,typeof(string)); //测试。 TDocument doc = new TDocument {Name =Zzz}; string name = convertedExpression.Compile()。Invoke(doc); Assert.Equal(Zzz,name);附录
<请注意,对于struct返回类型,最终的表达式可能会如下所示: (TDocument d)=> (INT)(对象)d.ID;
I have the following expression which is of type Expression<Func<TDocument, object>>
x => x.NameNow, I don't know the type of x.Name at compile time, but I now it at runtime since it's stored in a Type.
How can I convert my expression to be of type Expression<Func<TDocument, TOutput>> where TOutput is a Type and not known at compile time?
解决方案You just need to wrap the original expression's Body in a Convert expression and then rebuild your lambda. Here's how I would do it if I could use generics:
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 ); }Usage:
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);No generics
If you cannot use generics because you don't know the return type at compile time, Expression.Lambda actually offers a non-generic overload, which you can use like this:
Expression ConvertReturnValue<TInput>(Expression<Func<TInput, object>> inputExpression, Type returnType) { Expression convertedExpressionBody = Expression.Convert(inputExpression.Body, returnType); return Expression.Lambda(convertedExpressionBody, inputExpression.Parameters); }The above still returns an Expression<Func<TInput, TReturn>> (upcast to a non-generic Expression). You can downcast it later if you need to:
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);Addendum
Note that for struct return types, the final expression may end up looking like this:
(TDocument d) => (int)(object)d.ID;
更多推荐
转换表达< Func< TDocument,object>>表达<功能< T
发布评论