【发布时间】:2019-09-04 02:37:50
【问题描述】:
我有一个Expression<Func<Tin, object>> 对象,我需要将它转换为Expression<Func<Tin, Tout>> 对象。
其实我有这个:
x => new <>f__AnonymousType6`1(MyProp = x.MyProp)
我需要将其设置为:
x => new MyType(){MyProp = x.MyProp}
请注意,我在这里有一个AnonymousType!
为此,我编写了如下函数:
public static Expression<Func<Tin, Tout>> Transform<Tin, Tout>(this Expression<Func<Tin, object>> source)
{
var param = Expression.Parameter(typeof(Tout));
var body = new Visitor<Tout>(param).Visit(source.Body);
Expression<Func<Tin, Tout>> lambda = Expression.Lambda<Func<Tin, Tout>>(body, param);
return lambda;
}
还有一个访问者类:
class Visitor<T> : ExpressionVisitor
{
ParameterExpression _parameter;
public Visitor(ParameterExpression parameter)=>_parameter = parameter;
protected override Expression VisitParameter(ParameterExpression node)=>_parameter;
protected override Expression VisitMember(MemberExpression node)
{
if (node.Member.MemberType != System.Reflection.MemberTypes.Property)
throw new NotImplementedException();
var memberName = node.Member.Name;
var otherMember = typeof(T).GetProperty(memberName);
var inner = Visit(node.Expression);
return Expression.Property(inner, otherMember);
}
}
但是当我运行它时,我得到了这个错误:
System.ArgumentException: '类型的表达 'f__AnonymousType6`1[System.String]' 不能用于返回类型 '我的类型''
更新
在Tin 和Tout 类中,我有一些参数构造函数和一个私有无参数构造函数。我不想使用参数构造函数,因为它们的参数可能与所需的表达式不同。我需要使用私有无参数构造函数来构建表达式。
所以如果我使用下面的代码:
var ctor = typeof(TOut).GetPrivateConstructor();
if (ctor != null) // can replace
return Expression.New(ctor, node.Arguments);
甚至这个:
var ctor = typeof(TOut).GetPrivateConstructor();
if (ctor != null) // can replace
{
var expr = Expression.New(ctor);
expr.Update(node.Arguments);//<=====Exception in this line
return expr;
}
我会得到以下错误:
构造函数的参数数量不正确
如果我使用以下内容:
var ctor = typeof(TOut).GetPrivateConstructor();
if (ctor != null) // can replace
return Expression.New(ctor);
我会错过争论!
更新 2
如果我将其用作:
var ctor = typeof(TOut).GetPrivateConstructor();
if (ctor != null) // can replace
{
var expr = Expression.New(ctor);
FieldInfo argementsField = expr.GetType().GetRuntimeFields().FirstOrDefault(a => a.Name == "_arguments");
argementsField.SetValue(expr, node.Arguments);
expr.Update(node.Arguments);
return expr;
}
表达式将被构建,但不会被执行,因为它会产生以下内容:
x => new MyType(MyProp = x.MyProp)
再次不正确将按预期产生以下错误:
构造函数的参数数量不正确
【问题讨论】:
-
你能把你的 ExpressionVisitor 类添加到你的帖子中
-
@sayahimad ExpressionVisitor 是 .Net 中的内置类,位于 System.Linq.Expressions 命名空间中
-
@johnny5 我已更新问题以显示此问题与提到的可能重复问题之间的差异。
-
我已经解决了这个问题并遇到了其他问题。这是我的解决方案和新问题:stackoverflow.com/q/55730825/1666800
标签: c# expression func visitor-pattern