C# 将表达式强制转换为表达式
我有一个Expression对象,需要将其强制转换为Expression对象 事实上,我有:C# 将表达式强制转换为表达式,c#,expression,func,visitor,C#,Expression,Func,Visitor,我有一个Expression对象,需要将其强制转换为Expression对象 事实上,我有: x => new <>f__AnonymousType6`1(MyProp = x.MyProp) 请注意,我这里有一个匿名类型 为了实现这一点,我编写了如下函数: public static Expression<Func<Tin, Tout>> Transform<Tin, Tout>(this Expression<Func<Ti
x => new <>f__AnonymousType6`1(MyProp = x.MyProp)
请注意,我这里有一个匿名类型
为了实现这一点,我编写了如下函数:
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;
}
甚至这个:
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;
}
我会错过辩论的
更新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;
}
将生成表达式,但不会执行,因为它会生成以下内容:
var ctor = typeof(TOut).GetPrivateConstructor();
if (ctor != null) // can replace
return Expression.New(ctor);
x => new MyType(MyProp = x.MyProp)
如果再次出现错误,将产生以下预期错误:
构造函数的参数数目不正确
假设MyType看起来像这样
public class MyType
{
public MyType(string myProp)
{
MyProp = myProp;
}
public string MyProp { get; set; }
}
您可以创建一般访问者:
public class MyVisitor<TIn, TOut> : ExpressionVisitor
{
private readonly Type funcToReplace;
public MyVisitor()
{
funcToReplace = typeof(Func<,>).MakeGenericType(typeof(TIn), typeof(object));
}
// this hack taken from https://stackoverflow.com/a/2483054/4685428
// and https://stackoverflow.com/a/1650895/4685428
private static bool IsAnonymousType(Type type)
{
var markedWithAttribute = type.GetCustomAttributes(
typeof(CompilerGeneratedAttribute)).Any();
var typeName = type.Name;
return markedWithAttribute
&& typeName.StartsWith("<>")
&& typeName.Contains("AnonymousType");
}
protected override Expression VisitNew(NewExpression node)
{
if (IsAnonymousType(node.Type))
{
var arguments = node.Arguments.Select(a => a.Type).ToArray();
var ctor = typeof(TOut).GetConstructor(arguments);
if (ctor != null) // can replace
return Expression.New(ctor, node.Arguments);
}
return base.VisitNew(node);
}
protected override Expression VisitLambda<T>(Expression<T> node)
{
if (typeof(T) != funcToReplace)
return base.VisitLambda(node);
var p = node.Parameters.First();
var body = Visit(node.Body);
return Expression.Lambda<Func<TIn, TOut>>(body, p);
}
}
用法:
Expression<Func<TypeOfX, object>> input = x => new {MyProp = x.MyProp};
var visitor = new MyVisitor<TypeOfX, MyType>();
var result = (Expression<Func<TypeOfX, MyType>>) visitor.Visit(input);
一些解释:
在VisitNew中,我们检查构造函数是否属于匿名类型。如果是这样,我们将尝试在TOut类型中搜索具有相同参数的构造函数。成功后,我们将匿名类型构造函数替换为TOut的构造函数能否将ExpressionVisitor类添加到post@sayahimadExpressionVisitor是.Net中的一个内置类,它位于System.Linq.Expressions命名空间@johnny5的可能重复项我已更新了问题,以显示此问题与上面提到的可能重复的问题。我已经解决了这个问题,还面临其他问题。这是我的解决方案和新问题:我认为,从这个问题来看,对象代表了兜售者,所以很可能你只是想使用Convert@johnny5我不明白你的意思,抱歉。我的代码将对匿名构造函数的调用替换为对已定义构造函数(如果存在)的调用。我已经测试过了,它可以在OP输入上工作。你能不能用Expression.Convert示例发布另一个答案?我很高兴能学到一些新东西Expressions@alekz不,你是对的,我的错,我认为OP想要表达一个如title@AleksAndreev我已经更新了mu问题并添加了更多信息。谢谢您的时间和支持solution@AleksAndreev多亏了你的帮助,我解决了这个问题,也遇到了其他问题。以下是我的解决方案和新问题:
public class MyType
{
public MyType(string myProp)
{
MyProp = myProp;
}
public string MyProp { get; set; }
}
public class MyVisitor<TIn, TOut> : ExpressionVisitor
{
private readonly Type funcToReplace;
public MyVisitor()
{
funcToReplace = typeof(Func<,>).MakeGenericType(typeof(TIn), typeof(object));
}
// this hack taken from https://stackoverflow.com/a/2483054/4685428
// and https://stackoverflow.com/a/1650895/4685428
private static bool IsAnonymousType(Type type)
{
var markedWithAttribute = type.GetCustomAttributes(
typeof(CompilerGeneratedAttribute)).Any();
var typeName = type.Name;
return markedWithAttribute
&& typeName.StartsWith("<>")
&& typeName.Contains("AnonymousType");
}
protected override Expression VisitNew(NewExpression node)
{
if (IsAnonymousType(node.Type))
{
var arguments = node.Arguments.Select(a => a.Type).ToArray();
var ctor = typeof(TOut).GetConstructor(arguments);
if (ctor != null) // can replace
return Expression.New(ctor, node.Arguments);
}
return base.VisitNew(node);
}
protected override Expression VisitLambda<T>(Expression<T> node)
{
if (typeof(T) != funcToReplace)
return base.VisitLambda(node);
var p = node.Parameters.First();
var body = Visit(node.Body);
return Expression.Lambda<Func<TIn, TOut>>(body, p);
}
}
Expression<Func<TypeOfX, object>> input = x => new {MyProp = x.MyProp};
var visitor = new MyVisitor<TypeOfX, MyType>();
var result = (Expression<Func<TypeOfX, MyType>>) visitor.Visit(input);