【问题标题】:'Argument expression is not valid' when creating anonymous types dynamically动态创建匿名类型时“参数表达式无效”
【发布时间】:2019-01-25 08:50:49
【问题描述】:

我正在创建一个表达式树构建器来返回自定义匿名类型。我首先尝试使用离散类型,它工作正常,但是使用 TypeBuilder 在运行时构建类型并将该类型传递给表达式树失败并出现此错误

'Argument expression is not valid'

这是我使用的代码:

我用来创建匿名类型的这个方法

private Type CreateAnonymousType(Dictionary<string, Type> properties)
    {
      AssemblyName dynamicAssemblyName = new AssemblyName("MyAssembly");
      AssemblyBuilder dynamicAssembly = AssemblyBuilder.DefineDynamicAssembly(dynamicAssemblyName, AssemblyBuilderAccess.Run);
      ModuleBuilder dynamicModule = dynamicAssembly.DefineDynamicModule("MyAssembly");

      TypeBuilder dynamicAnonymousType = dynamicModule.DefineType("ReturnType", TypeAttributes.Public | TypeAttributes.Class | TypeAttributes.AutoClass);
      foreach (var p in properties)
      {
        dynamicAnonymousType.DefineField(p.Key, p.Value, FieldAttributes.Public);
      }

      return dynamicAnonymousType.CreateType();
    }

这是我创建表达式树的方法

var cars = new List<Car>();
      for (int i = 0; i < 10; i++)
      {
        cars.Add(new Car { Id = i, Name = "Car " + i, Age = 2010 + i });
      }


      IQueryable<Car> allCars = cars.AsQueryable();

      var properties = new Dictionary<string, Type>
      {
        { "Id", typeof(int) },
        { "Name", typeof(string) }
      };

      ParameterExpression x = Expression.Parameter(typeof(Car), "x");
      var listMembers = properties.Select(p => Expression.Property(x, p.Key));

      var returnType = CreateAnonymousType(properties);
      object destObject = Activator.CreateInstance(returnType);


      var listBind = listMembers.Select(p => Expression.Bind(returnType.GetField(p.Member.Name), p));

      var result = Expression.New(returnType);
      var initExp = Expression.MemberInit(result, listBind.ToArray());


      var call = Expression.Call(typeof(Queryable), "Select",
          new Type[] {
            typeof(Car),
            returnType
        }
        , Expression.Constant(allCars)
        , Expression.Lambda(initExp, x));

      var qResult = allCars.Provider.CreateQuery<IdName>(call);

      foreach (var car in qResult)
      {
        Console.WriteLine(car.Id + " - " + car.Name);
      }

执行 CreateQuery 方法时发生的错误

【问题讨论】:

    标签: linq expression-trees typebuilder


    【解决方案1】:

    这是因为 call 返回动态创建的 ReturnType 而不是 IdName 因此异常。此外,您不能将诸如 ReturnType 之类的动态类型作为泛型类型参数,因为编译器对它们一无所知,因此您应该改用 dynamic,以便在运行时解析类型:

    var qResult = allCars.Provider.CreateQuery<dynamic>(call);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-04-30
      • 1970-01-01
      • 2023-04-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-14
      相关资源
      最近更新 更多