转换表达< Func< TDocument,object>>表达<功能< TDocument,TOutput>> [英] Convert Expression<Func<TDocument, object>> to Expression<Func<TDocument, TOutput>>
问题描述
我有以下表达式,类型为表达式< 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 convertedExpressionBody,inputExpression.Parameters
);
}
用法:
表达式< Func< TDocument,object>> inputExpression = d => d.Name;
表达式< Func< TDocument,string>> convertedExpression
= ConvertReturnValue< TDocument,string>(inputExpression);
//测试。
TDocument doc = new TDocument {Name =Zzz};
string name = convertedExpression.Compile()。Invoke(doc);
Assert.Equal(Zzz,name);
无泛型
如果您不能使用泛型,因为您在编译时不知道返回类型, 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.Name
Now, 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>>表达<功能< TDocument,TOutput>>的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!