Question

    

Cette question a déjà une réponse ici:

         

nous devons évaluer une valeur dans un objet au moment de l'exécution tout en ayant une déclaration textuelle du chemin d'accès exact au membre, par exemple: myobject.firstMember.secondMember [3] .text
nous avons envisagé d'analyser cette déclaration textuelle à l'aide de regex, puis d'évaluer la valeur du texte à l'aide de la réflexion, mais auparavant, je me demande si C # prend en charge une sorte de capacité eval ? Nous n'aurons donc pas à nous analyser nous-mêmes. Comment Microsoft fait-il cela dans sa fenêtre immédiate ou regarde-t-il les fenêtres?

merci beaucoup,

Adi Barda

Était-ce utile?

La solution

La solution la plus simple consiste probablement à utiliser DataBinder .Eval de System.Web.UI:

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

Autres conseils

J'ai écrit un projet open source, Dynamic Expresso , permettant de convertir une expression textuelle écrite à l'aide d'un Syntaxe C # en délégués (ou arbre d’expression). Les expressions sont analysées et transformées en arbres d'expression sans utiliser la compilation ou la réflexion.

Vous pouvez écrire quelque chose comme:

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

ou

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

Mon travail est basé sur l'article de Scott Gu http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic- query-library.aspx .

À l’avenir (autour de la période 5.0), le "compilateur en tant que service" peut être capable de faire cela. En fait, vous pourrez peut-être faire beaucoup de choses maintenant avec "mono". (voir CsharpRepl et Mono.CSharp - cependant, je pense qu'il faudra en savoir beaucoup plus sur le contexte pour pouvoir utiliser les paramètres locaux. variables etc dans Évaluer ) - mais cela n’est pas pris en charge dans l’offre MS .NET actuelle.

Pour l'instant, vous devez définir une partie de ce que fait le code de liaison de données ... en le séparant par des jetons tels que ".". et utiliser la réflexion. Strictement parlant, le code de liaison utilise en réalité TypeDescriptor / PropertyDescriptor plutôt que la réflexion directe, mais l'effet est le même.

Bien que l'approche soit un peu lourde, vous pouvez utiliser C # CodeDom pour émettre un nouvel assemblage contenant une méthode contenant uniquement cette ligne de code.

C’est beaucoup plus brutal que certaines des autres suggestions, j’admets, mais vous laissez l’analyseur C # faire le gros du travail, il devrait donc être capable de gérer tout ce que vous lui lancez tant que c'est valide C #.

Si vous suivez cette route, vous devez également vous assurer que vous pouvez décharger à nouveau l'assembly émis. Il peut donc être nécessaire de créer et de décharger AppDomains.

J'ai implémenté et utilisé avec succès la technique ci-dessus. D'autre part, si vous pouvez utiliser un DynamicMethod il serait beaucoup plus léger. Cependant, je n'ai jamais essayé cette approche et je ne peux donc pas vous dire si vous pouvez implémenter un corps DynamicMethod à l'aide de littéraux C #.

En fait, la fonctionnalité d'évaluation des expressions et de moteur de règles de Windows Workflow Foundation peut effectuer des opérations de ce type. Voir Présentation du moteur de règles de base de flux de travail Windows .

Un aspect intéressant de ces composants est qu’ils ont été conçus pour que vous puissiez héberger les composants de conception dans vos propres applications afin de concevoir des ensembles de règles et / ou d’expressions qui fonctionnent dans le contexte de vos propres classes personnalisées. Par exemple, vous lui diriez de concevoir une expression contre "myObject" et il saurait qu'il existe un firstMember qui a un secondMember qui a un indexeur produisant un type ayant une propriété text. Vous pouvez conserver les expressions et les règles au format XML et les relire au moment de l'exécution, sans avoir à utiliser le concepteur au moment de l'exécution.

En particulier, voir Exemple de kit de règles externe RuleSet Toolkit .

Malheureusement, C # ne dispose d'aucune fonctionnalité native pour faire exactement ce que vous demandez.

Cependant, mon programme C # eval permet d’évaluer le code C #. Il permet d'évaluer le code C # au moment de l'exécution et prend en charge de nombreuses instructions C #, y compris des expressions telles que " myobject.firstMember.secondMember [3] .text ". En fait, ce code est utilisable dans tout projet .NET, mais il est limité à l’utilisation de la syntaxe C #. Consultez mon site Web, http://csharp-eval.com , pour plus de détails.

Vous pouvez toujours essayer mon programme léger C # Eval. Il compile un sous-ensemble substantiel du langage C # en méthodes dynamiques. Détails complets sur le référentiel GitHub DavidWynne / CSharpEval

Autant que je sache, il n’existe pas de fonction Eval intégrée. Vous devrez suivre le chemin Regex + Reflection. Je pense également que Visual Studio fait de même.

Voici quelque chose de similaire que j'utilise pour trouver des propriétés imbriquées de manière dynamique. Vous devez ajouter la logique pour les indexeurs ... et des vérifications supplémentaires ... j'attrape des NULL / des erreurs dans ma méthode d'appel ...

  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;
  }
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top