Pregunta

    

Esta pregunta ya tiene una respuesta aquí:

         

necesitamos evaluar un valor en un objeto en tiempo de ejecución mientras tenemos una declaración textual de la ruta exacta del miembro, por ejemplo: myobject.firstMember.secondMember [3] .text
pensamos en analizar esta declaración textual usando expresiones regulares y luego evaluar el valor del texto usando la reflexión, pero antes de hacerlo, me pregunto si C # admite algún tipo de habilidad eval . así que no tendremos que analizarlo nosotros mismos. ¿Cómo hace Microsoft esto en su ventana inmediata o mira ventanas?

muchas gracias,

Adi Barda

¿Fue útil?

Solución

Probablemente la forma más fácil es usar DataBinder .Eval de System.Web.UI:

var foo = new Foo() { Bar = new Bar() { Value = "Value" } };
var value = DataBinder.Eval(foo, "Bar.Value");

Otros consejos

He escrito un proyecto de código abierto, Dynamic Expresso , que puede convertir la expresión de texto escrita usando un Sintaxis de C # en delegados (o árbol de expresión). Las expresiones se analizan y transforman en Árboles de expresión sin usar compilación o reflexión.

Puedes escribir algo como:

var interpreter = new Interpreter();
var result = interpreter.Eval("8 / 2 + 2");

o

var interpreter = new Interpreter()
                .SetVariable("service", new ServiceExample());

string expression = "x > 4 ? service.SomeMethod() : service.AnotherMethod()";

Lambda parsedExpression = interpreter.Parse(expression, 
                        new Parameter("x", typeof(int)));

parsedExpression.Invoke(5);

Mi trabajo se basa en el artículo de Scott Gu http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic- query-library.aspx .

En el futuro (alrededor del marco de tiempo 5.0), el compilador como servicio puede ser capaz de hacer esto. En realidad, puede hacer mucho de esto ahora con "mono" (consulte CsharpRepl y Mono.CSharp - sin embargo, espero que necesite saber mucho más sobre el contexto para poder usar local variables, etc. en Evaluar ) - pero no hay ningún soporte para esto en la oferta actual de MS .NET.

Por ahora, tendría que hacer algo como lo que hace gran parte del código de enlace de datos ... dividirlo en tokens como ". " y usa la reflexión. Estrictamente hablando, el código de enlace en realidad usa TypeDescriptor / PropertyDescriptor en lugar de la reflexión directa, pero el efecto es el mismo.

Aunque es un enfoque algo pesado, puede usar C # CodeDom para emitir un nuevo ensamblaje nuevo que contenga un método con solo esa línea de código.

Admito que esto es mucho más duro que algunas de las otras sugerencias, pero por otro lado, dejas que el analizador C # haga el trabajo pesado, por lo que debería ser capaz de manejar todo lo que le arrojes mientras es válido C #.

Si sigue esa ruta, también debe asegurarse de que puede descargar el ensamblaje emitido nuevamente, por lo que puede ser necesario crear y descargar AppDomains.

He implementado y utilizado con éxito la técnica anterior. Por otro lado, si puede usar un DynamicMethod sería mucho más ligero. Sin embargo, nunca he intentado ese enfoque, por lo que no puedo decir si puede implementar el cuerpo de un DynamicMethod usando literales de C #.

En realidad, la función de motor de reglas y evaluación de expresiones de Windows Workflow Foundation puede hacer cosas como esta. Consulte Introducción al motor de reglas de Windows Workflow Foundation .

Una cosa interesante sobre estos componentes es que fueron diseñados para que pueda alojar los componentes en tiempo de diseño en sus propias aplicaciones para diseñar conjuntos de reglas y / o expresiones que operan en el contexto de sus propias clases personalizadas. Por ejemplo, le diría que diseñe una expresión contra '' myObject '', y sabría que hay un primer miembro que tiene un segundo miembro que tiene un indexador que produce un tipo que tiene una propiedad de texto. Puede conservar las expresiones y reglas como XML y volver a leerlas en tiempo de ejecución, sin necesidad de utilizar el diseñador en tiempo de ejecución.

En particular, consulte Ejemplo de kit de herramientas de conjunto de reglas externo .

Desafortunadamente, C # no tiene instalaciones nativas para hacer exactamente lo que está pidiendo.

Sin embargo, mi programa de evaluación C # permite evaluar el código C #. Proporciona la evaluación del código de C # en tiempo de ejecución y admite muchas declaraciones de C #, incluidas expresiones como " myobject.firstMember.secondMember [3] .text " ;. De hecho, este código es utilizable en cualquier proyecto .NET, sin embargo, se limita al uso de la sintaxis de C #. Eche un vistazo a mi sitio web, http://csharp-eval.com , para obtener detalles adicionales.

Siempre puedes probar mi ligero programa C # Eval. Compila un subconjunto sustancial del lenguaje C # a métodos dinámicos. Detalles completos en mi repositorio de GitHub DavidWynne / CSharpEval

AFAIK no existe tal función de evaluación incorporada. Tendrás que seguir el camino Regex + Reflection. También creo que Visual Studio está haciendo lo mismo.

Aquí hay algo similar que estoy usando para encontrar propiedades dinámicamente anidadas ... necesitaría agregar la lógica para los indexadores ... y algunas comprobaciones adicionales ... Estoy captando nulos / errores en mi método de llamada ...

  public static object FindDottedProperty(this object input, string propertyName)
  {
    if (input == null)
      return null;

    if (string.IsNullOrEmpty(propertyName))
      return null;

    Queue props = new Queue(propertyName.Split('.'));
    if (props.Count == 0) return null;

    //start with input object and roll out property stack from there.
    object ret = input;
    while (props.Count > 0)
    {
      var prop = props.Dequeue();
      if (string.IsNullOrEmpty(prop)) return null;

      /*** ADD INDEXER LOGIC HERE ***/

      //get the property's value based on the current named item
      ret = ret.GetType().GetProperty(prop).GetValue(ret, null);

      if (null.Equals(ret)) return null;
    }

    //return looked up value
    return ret;
  }
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top