![](/img/trans.png)
[英]Convert Expression<Func<T, object>> to Expression<Func<object>>
[英]Convert Expression<Func<XClass, object>> to Expression<Func<YClass, object>>
我想创建通过查询获取项目的存储库模式类。 不幸的是,我需要将此查询从一个类解析到另一个类(从图片到ListItem),以将其发送到服务器(API)。 所以我的代码应如下所示:
public static void ConvertQuery(Expression<Func<Picture, object>> oldQuery)
{
Expression<Func<ListItem, object>> newQuery = convert(oldQuery);
}
并且,例如,我想通过如下所示的转换属性来转换旧查询:
我找到了一些可以投射属性的解决方案。 但是最大的问题是将一个属性转换为字典字段(item1.Filename为item2。[“ Filename”])
更新资料
@nejcs
我尝试使用您的解决方案,但不幸的是我有例外:
System.ArgumentException:类型'Microsoft.SharePoint.Client.ListItem'的ParametersExpression不能用于类型'CastExpression.Picture'的委托参数
属性“ Item”负责字典值,但是我认为转换存在问题。 以下是stackTrace:
在System.Linq.Expressions.Expression.ValidateLambdaArgs(类型委托类型,表达式和主体,ReadOnlyCollection 1参数)在System.Linq.Expressions.Expression.Lambda [TDelegate](系统处的表达式主体,字符串名称,布尔值tailCall,IEnumerable 1参数) .Linq.Expressions.Expression 1.在System.Linq.Expressions.Expression 1.Update(Expression body,IEnumerable`1参数)在System.Linq.Expressions.Expression 1.Update(Accept(ExpressionVisitor visitor) )在System.Linq.Expressions.ExpressionVisitor.Visit(Expression节点)
在CastExpression.Program.Main(String [] args)
我也知道表情主体的样子
对于oldClassQuery:
Expression<Func<Picture, object>> oldQuery = x => x.FileName == "AS";
{x => Convert((x.FileName ==“ AS”))}
对于newClassQuery:
Expression<Func<ListItem, object>> newQuery = x => x["FileName"] == "AS";
{x => Convert((x.get_Item(“ FileName”)==“ AS”))}
您正在寻找ExpressionVisitor 。 只需通过扩展此类并覆盖适当的方法来创建自定义样式,即可将子表达式从一种形式转换为另一种形式。
例如,要转换成员访问权限,您将执行以下操作(绝不完成):
public class RewritingVisitor : ExpressionVisitor
{
private readonly ParameterExpression p = Expression.Parameter(typeof(ListItem)); // create new parameter which will be referenced later
protected override Expression VisitParameter(ParameterExpression node)
{
if (node.Type == typeof(Picture))
{
return p;
}
return node;
}
protected override Expression VisitMember(MemberExpression node)
{
var rewritten = Visit(node.Expression);
if (rewritten == node.Expression) return node;
if (node.Expression != null &&
node.Expression.Type == typeof(Picture) &&
rewritten.Type == typeof(ListItem))
{
if (node.Member.Name == "Id")
{
return Expression.MakeMemberAccess(
rewritten,
typeof(ListItem).GetProperty("Id"));
}
else if (node.Member.Name == "FileName")
{
return Expression.MakeIndex(
rewritten,
typeof(ListItem).GetProperty("Item"), // default indexer name
new[] { Expression.Constant("FileName") });
}
}
}
}
然后,您可以通过简单地实例化它并使用lambda表达式作为参数来调用Visit
方法来使用它:
var visitor = new RewritingVisitor();
var newQuery = visitor.Visit(oldQuery);
编辑:
我忘记了一个很小但相当重要的部分:如果子表达式被更新,则默认情况下,访问者将在传入新值的表达式上调用update(或类似方法)。 在使用lambda表达式的情况下,验证逻辑期望表达式与原始类型相同,但那当然是不正确的。 您必须从访问的部分中手动构造新的lambda表达式:
protected override Expression VisitLambda<T>(Expression<T> node)
{
var lambdaExpr = (LambdaExpression)node;
var rewrittenParameters = lambdaExpr.Parameters.Select(x => (ParameterExpression)Visit(x)).ToArray();
var rewrittenBody = Visit(lambdaExpr.Body);
return Expression.Lambda(rewrittenBody, rewrittenParameters);
}
这是您的访问者中缺少的重写,它负责从重写的参数和lambda主体创建新的lambda。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.