'L'expression d'argument n'est pas valide' lors de la création dynamique de types anonymes

expression-trees linq typebuilder

Question

Je crée un générateur d'arbre d'expression pour renvoyer des types anonymes personnalisés. J'ai d'abord essayé avec des types discrets et cela fonctionne bien, mais l'utilisation de TypeBuilder pour créer des types au moment de l'exécution et passer ce type à l'arbre d'expression échoue avec cette erreur

'Argument expression is not valid'

voici le code que j'utilise:

cette méthode que j'utilise pour créer le type anonyme

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

et voici comment je crée l'arbre d'expression

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

l'erreur est survenue pendant l'exécution de la méthode CreateQuery

Réponse acceptée

En effet , l' call des rendements dynamiquement créés ReturnType IdName donc l'exception. En outre, vous ne pouvez pas ReturnType des types dynamiques tels que ReturnType tant que paramètres de type générique, car le compilateur n'en sait rien, vous devez donc utiliser dynamic pour que le type soit résolu au moment de l'exécution:

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


Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi