Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/294.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 将表达式强制转换为表达式_C#_Expression_Func_Visitor - Fatal编程技术网

C# 将表达式强制转换为表达式

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

我有一个Expression对象,需要将其强制转换为Expression对象

事实上,我有:

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);