Quiero invocar a un método que espera un parámetro como este:

Expression<Func<sometype, 'a>> expr

Necesito para la construcción de este parámetro en tiempo de ejecución, porque no voy a saber lo que el tipo anónimo se verá como antes; podría tener cualquier cantidad de campos:

x => new { a=x.a, b=x.b, c=x.c, etc... }

Puedo crear un tipo en tiempo de ejecución que tiene el mismo ‘firma’ (que Es la palabra correcta para esto?) como el deseado de tipo anónimo, pero la pregunta es: ¿Cómo puedo construir esta expresión lambda en tiempo de ejecución a partir de eso? Especialmente Expresión.De nuevo es que me molesta, porque necesito pasar un constructorInfo que tengo que conseguir a partir de un tipo existente (que de hecho puede ser un tipo anónimo, pero que no se puede crear un tipo anónimo en tiempo de ejecución. O hay una manera de hacer eso?).

Actualización (un poco de contexto, como se pide en los comentarios)

El método quiero invocar es:

DependentNavigationPropertyConfiguration.HasForeignKey<TKey>(Expression<Func<TDependentEntityType, TKey>> foreignKeyExpression)

La razón por la que yo quiero hacer, esto es para realizar automáticamente una propiedad de navegación a una entidad que hereda de una cierta clase base incluir la clave de la clase base en la clave externa. Debido a que una entidad puede tener múltiples campos de la clave de cualquier tipo, el tipo TKey es sólo para mí en tiempo de ejecución.

  • ¿Cuál es la entrada de usted escenario? ¿Construir en tiempo de ejecución de la cadena de base de datos?
  • En tiempo de ejecución de un número de campos seleccionados de ‘sometype’. Necesito construir la expresión de eso. Los nombres de los campos del tipo anónimo son los mismos que los campos que fueron seleccionados de ‘sometype’.
  • ¿Por qué el downvote? Por favor explique lo que yo podría aprender algún día.

3 Comentarios

  1. 10

    Utilización de un método:

    public static void Main()
    {
        var myExpression = Express(str => new { 
            String = str, 
            Length = str.Length 
        });
    
        //We can compile/use it as well...
        var compiledExpression = myExpression.Compile();
        var anonymousOutput = compiledExpression("Input String");
    
        Console.WriteLine(anonymousOutput.String); //Output: Input String
        Console.WriteLine(anonymousOutput.Length); //Output: 12
    
        Debug.WriteLine(myExpression); //Output: "str => new <>f__AnonymousType0`2(String = str, Length = str.Length)"
        Console.ReadLine();
    }
    
    
    static Expression<Func<String, T>> Express<T>(Expression<Func<String, T>> expression)
    {
        return expression;
    }

    Nota sin embargo, que el tipo de partida (en mi ejemplo String) debe ser conocida hasta la frente.

    Actualización:

    Ya que lo que suena como que usted está tratando de hacer es crear dinámicamente un tipo, te voy a dar un ejemplo sencillo de cómo hacerlo.

    public static void Main()
    {
            //Create an anonymous type with two fields
        Type myAnonymousType = CreateNewType<String, Int32>();
        dynamic myAnon = Activator.CreateInstance(myAnonymousType);
    
        myAnon.FieldA = "A String";
        myAnon.FieldB = 1234;
    
    
        Console.WriteLine(myAnon.FieldA); //Output : "AString"
        Console.WriteLine(myAnon.FieldB); //Output : 1234
        Console.ReadLine();
    }
    
    public static Type CreateNewType<TFieldTypeA, TFieldTypeB>()
    {
        //Let's start by creating a new assembly
        AssemblyName dynamicAssemblyName = new AssemblyName("MyAsm");
        AssemblyBuilder dynamicAssembly = AssemblyBuilder.DefineDynamicAssembly(dynamicAssemblyName, AssemblyBuilderAccess.Run);
        ModuleBuilder dynamicModule = dynamicAssembly.DefineDynamicModule("MyAsm");
    
        //Now let's build a new type
        TypeBuilder dynamicAnonymousType = dynamicModule.DefineType("MyAnon", TypeAttributes.Public);
    
        //Let's add some fields to the type.
        FieldInfo dynamicFieldA = dynamicAnonymousType.DefineField("FieldA", typeof(TFieldTypeA), FieldAttributes.Public);
        FieldInfo dynamicFieldB = dynamicAnonymousType.DefineField("FieldB", typeof(TFieldTypeB), FieldAttributes.Public);
    
        //Return the type to the caller
        return dynamicAnonymousType.CreateType();
    }

    Como se puede ver, este es un poco más complicado. Si quieres estudiar el tema más a fondo, aunque, sin duda referencia Reflectoin.Emit.

    • Gracias, ese es un buen truco, pero, por desgracia, no resuelve mi problema principal, a saber, que no sé lo que el tipo anónimo verá hasta en tiempo de ejecución (cantidad de campos es variable). Así que realmente no puedo hacer que la expresión en cualquier lugar.
    • Oh, ya veo. Así, que con lo que es, un tipo anónimo es una característica del compilador, es decir, cuando se escribe un anónimo, el compilador genera a una determinada clase con un nombre al azar (en mi ejemplo <>f__AnonymousType0'2). Así que realmente no se puede fácil crear un tipo anónimo en tiempo de ejecución. Usted puede conseguir lejos con usar Expression.New, pero que requiere de un constructor, lo que implica que debe ser de un tipo existente. Usted puede definir un nuevo tipo de solucionar este problema, pero en realidad eso es totalmente independiente de la pregunta. Si quiere me puede escribir un ejemplo.
    • Actualizado respuesta.
    • Gracias de nuevo por tu problema. Sé cómo crear el tipo I de la necesidad de uso de la reflexión, pero el problema es que, el uso de ese tipo, que no se puede crear una expresión que crea un nuevo tipo anónimo. He añadido un poco de contexto a mi pregunta original. Si invoco el método mencionado con una expresión creada a partir de una recién creada tipo a través de la reflexión, obtengo una excepción que me dice el tipo de expresión no encaja, ya que espera que sea una expresión de propiedad, o uno con un tipo anónimo…
    • Estoy teniendo problemas con esta parte: I can't create an expression that creates a new anonymous type. Un tipo anónimo es una característica del compilador sólo disponible en tiempo de compilación. No se puede crear un «tipo anónimo» en tiempo de ejecución. Usted puede crear un nuevo tipo sí mismo, pero que no es estrictamente hablando una «anónima de tipo».
    • Lo que quiero decir es que puedo crear esta expresión: x=>nuevo MyAnonymousType() {a=x.a, b=x.b}, pero no puedo crear x=>nuevo {a=x.a, b=x.b} es El método que yo estoy tratando de invocar espera que el segundo tipo de expresión (sin tipo explícito).

  2. 3

    Tipos anónimos son una característica del compilador. Si usted no recibe el compilador para crear en tiempo de compilación, entonces usted tendrá el uso de meta-programación – ya sea TypeBuilder o tal vez CSharpCodeProvider. Usted puede ser mejor usar tuplas – al menos ellos son fáciles de crear (puede utilizar Tuple.Create con bastante facilidad).

    Como para la expresión; sugiero escribir como Expression<Func<sometype, object>> – que funcionará para cualquier formulación. El código la inspección de la Expression, por supuesto, pueden ver lo que el tipo real es.

  3. -8

    que usted puede hacer simplemente como esta

    context.Students.Join(context.Courses, a => a.Course_id, b => b.Course_id, (a, b) => new { Student= a, Course= b }).Where(x => x.Student_id == studentId)
          .Select(y => new
          {
             StudentId = y.Student.StudentId,
             RegistrationNumber = y.Student.RegNo,
             Name = y.Student.Name,
             Coursename = y.Course.Name
          }).ToList();
    • ¿Cómo esta la respuesta a la pregunta?
    • Usted puede obtener un tipo anónimo en tiempo de ejecución sin necesidad de llenar los datos en un tipo conocido. No pueden ser muy relevantes a la pregunta, pero útil
    • Es importante entender, que new declaraciones como en tu ejemplo no son la creación de tipos anónimos en tiempo de compilación. Es por eso que esta respuesta no tiene nada que ver con la pregunta y por lo tanto no es útil en absoluto.

Dejar respuesta

Please enter your comment!
Please enter your name here