Pregunta

Estoy trabajando en un método que acepta un árbol de expresiones como parámetro, junto con un tipo (o instancia) de una clase.

La idea básica es que este método agregará ciertas cosas a una colección que se usará para la validación.

public interface ITestInterface
{
    //Specify stuff here.
}

private static void DoSomething<T>(Expression<Func<T, object>> expression, params IMyInterface[] rule)
{
    // Stuff is done here.
}

El método se llama de la siguiente manera:

class TestClass
{
    public int MyProperty { get; set; }
}

class OtherTestClass  : ITestInterface
{
    // Blah Blah Blah.
}

static void Main(string[] args)
{
    DoSomething<TestClass>(t => t.MyProperty, 
        new OtherTestClass());
}

Lo hago de esta manera porque me gustaría que los nombres de las propiedades que se pasan sean escritos con fuerza.

Un par de cosas con las que estoy luchando ...

  1. Dentro de DoSomething, me gustaría obtener un tipo PropertyInfo (del cuerpo pasado) de T y agregarlo a una colección junto con la regla []. Actualmente, estoy pensando en usar expression.Body y eliminar [propertyname] de " Convert. ([Propertyname]) " y usando la reflexión para conseguir lo que necesito. Esto parece engorroso y equivocado. ¿Hay una mejor manera?
  2. ¿Es este un patrón específico que estoy usando?
  3. Por último, cualquier sugerencia o aclaración sobre mi falta de comprensión de lo que estoy haciendo son apreciadas y / o los recursos o buena información sobre los árboles de expresión de C # también son apreciados.

¡Gracias!

Ian

Editar:

Un ejemplo de lo que expression.Body.ToString () devuelve dentro del método DoSomething es una cadena que contiene " Convert (t.MyProperty) " si se llama desde el ejemplo anterior.

Necesito que se escriba con fuerza, por lo que no se compilará si cambio el nombre de una propiedad.

Gracias por las sugerencias!

¿Fue útil?

Solución

La recopilación de objetos PropertyInfo de Expression.Body parece similar a Mi solución a otra pregunta.

Otros consejos

Confío en gran medida en los árboles de expresiones para impulsar gran parte de lo que quiero hacer con mi aplicación actual en tiempo de compilación, es decir, la comprobación de tipos estática.

Atravieso los árboles de expresiones para traducirlos a otra cosa que " tiene sentido " ;.

Una cosa que terminé haciendo mucho es que, en lugar de las URL, confío en un enfoque de tipo MVC en el que declaro funciones lambda y traduce que ... el compilador genera el árbol de expresiones en una URL. Cuando se invoca esta URL, hago lo contrario. De esta manera, tengo lo que llamo verificaciones en tiempo de compilación para los enlaces rotos y esto funciona muy bien con refactorización y sobrecargas también. Creo que es genial pensar en usar árboles de expresión de esta manera.

Es posible que desee revisar el patrón de visitantes, es un dolor comenzar porque no tiene mucho sentido al principio, pero une todo y es una forma muy formal de resolver la comprobación de tipos en la construcción de compiladores. Podría hacer lo mismo, pero en lugar de la comprobación de tipos, emita lo que necesite.

Algo contra lo que estoy golpeando mi cabeza en este momento es la capacidad de construir un marco simple para traducir (o en realidad debería decir interpretar) la expresión y emitir JavaScript. La idea es que los árboles de expresión generados por el compilador se traducirán a JavaScript válido que se interconecta con algún modelo de objeto.

Lo interesante de esto es la forma en que el compilador siempre puede decirme cuándo me equivoco y estoy seguro de que el resultado final es solo un montón de cadenas, pero la parte importante es cómo se crearon estas cadenas. Pasaron por alguna verificación y eso significa algo.

Una vez que lo hayas hecho, hay poco que no puedas hacer con los árboles de expresiones.

Mientras trabajaba con System.Reflection.Emitir cosas, me encontré usando árboles de expresiones para crear un marco de trabajo ligero para la compilación dinámica, que en el momento de la compilación básicamente podría decir si mis ensamblajes creados dinámicamente también se compilarían, y esto funcionó. Perfectamente con reflexión y comprobación de tipos estáticos. Esto fue más allá y terminó con algo que, al final, ahorró mucho tiempo y resultó ser muy ágil y robusto.

Así que me encanta este tipo de cosas, y de esto se trata la meta programación, escribir programas en tus programas que hacen programas. ¡Digo que siga viniendo!

Aprecio lo que intentas hacer con la propiedad aquí. Me he topado con este enigma. Siempre se siente raro escribir:

DoSomething("MyProperty", new OtherClass());

Si la propiedad cambia de nombre o el texto se escribe mal en la llamada, habrá un problema. Lo que he aprendido es que esto es algo con lo que probablemente tendrá que lidiar a través de las pruebas. En concreto, la prueba unitaria. Escribiría pruebas unitarias para hacer cumplir que " DoSomething " Las llamadas funcionan correctamente.

La otra cosa que podrías intentar es decorar tus propiedades con atributos, y luego reflexionar sobre tu clase cuando se construye buscando propiedades con el atributo y reglas de carga.

[DoSomething(typeof(OtherClass), typeof(OtherClass2))]
public int MyProperty
{
  get;
  set;
}

En este caso, el constructor (¿quizás en una clase base?) crearía dinámicamente un objeto OtherClass y un objeto OtherClass2, y los cargaría en una colección junto con el nombre de la propiedad.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top