gpt4 book ai didi

c# - 将 Expression> 转换为 Expression>,反之亦然

转载 作者:太空狗 更新时间:2023-10-29 22:37:05 25 4
gpt4 key购买 nike

有没有办法转换属性选择器Expression<Func<T, TProperty>>Expression<Func<object, object>>反之亦然?我已经知道如何转换为 Expression<Func<T, object>>使用...

Expression<Func<T, TProperty>> oldExp;
Expression.Lambda<Func<T, object>>(Expression.Convert(oldExp.Body, typeof(object)), oldExp.Parameters);

...但我需要有效地转换函数的参数和结果,而不仅仅是例如用 ExpressionVisitor 替换它们因为他们需要稍后再投回去。

最佳答案

您是正确的,您需要使用 ExpressionVisitor 和 ExpressionConvert。

以下是您要求的两种方法(以及一些支持方法):

public Expression<Func<object, object>> ConvertToObject<TParm, TReturn>(Expression<Func<TParm, TReturn>> input)
{
var parm = Expression.Parameter(typeof(object));
var castParm = Expression.Convert(parm, typeof(TParm));
var body = ReplaceExpression(input.Body, input.Parameters[0], castParm);
body = Expression.Convert(body, typeof(object));
return Expression.Lambda<Func<object, object>>(body, parm);
}

public Expression<Func<TParm, TReturn>> ConvertBack<TParm, TReturn>(Expression<Func<object, object>> input)
{
var parm = Expression.Parameter(typeof(TParm));
var castParm = Expression.Convert(parm, typeof(object));
var body = ReplaceExpression(input.Body, input.Parameters[0], castParm);
body = Expression.Convert(body, typeof(TReturn));
return Expression.Lambda<Func<TParm, TReturn>>(body, parm);
}

Expression ReplaceExpression(Expression body, Expression source, Expression dest)
{
var replacer = new ExpressionReplacer(source, dest);
return replacer.Visit(body);
}

public class ExpressionReplacer : ExpressionVisitor
{
Expression _source;
Expression _dest;

public ExpressionReplacer(Expression source, Expression dest)
{
_source = source;
_dest = dest;
}

public override Expression Visit(Expression node)
{
if (node == _source)
return _dest;

return base.Visit(node);
}
}

示例用法:

Expression<Func<Customer, string>> expression = c => c.Name;
var convertedExpression = ConvertToObject<Customer, string>(expression);
var backExpression = ConvertBack<Customer, string>(convertedExpression);

当然我们可以把原来的两个方法换成一个方法多一些类型参数:

public Expression<Func<TTargetParm, TTargetReturn>> ConvertGeneric<TParm, TReturn, TTargetParm, TTargetReturn>(Expression<Func<TParm, TReturn>> input)
{
var parm = Expression.Parameter(typeof(TTargetParm));
var castParm = Expression.Convert(parm, typeof(TParm));
var body = ReplaceExpression(input.Body, input.Parameters[0], castParm);
body = Expression.Convert(body, typeof(TTargetReturn));
return Expression.Lambda<Func<TTargetParm, TTargetReturn>>(body, parm);
}

示例用法:

Expression<Func<Customer, string>> expression = c => c.Name;
var convertedExpression = ConvertGeneric<Customer, string, object, object>(expression);
var backExpression = ConvertGeneric<object, object, Customer, string>(convertedExpression);

关于c# - 将 Expression<Func<T, TProperty>> 转换为 Expression<Func<object, object>>,反之亦然,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26253321/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com