Domanda

    

Questa domanda ha già una risposta qui:

         

dobbiamo valutare un valore in un oggetto in fase di esecuzione mentre abbiamo un'istruzione testuale del percorso esatto del membro, ad esempio: myobject.firstMember.secondMember [3] .text
abbiamo pensato di analizzare questa affermazione testuale usando regex e quindi valutare il valore del testo usando la riflessione, ma prima di fare ciò mi chiedo se C # supporti qualche tipo di abilità valutazione ? quindi non dovremo fare noi stessi l'analisi. Come fanno Microsoft a farlo nella loro finestra immediata o guardare le finestre?

grazie mille

Adi Barda

È stato utile?

Soluzione

Probabilmente il modo più semplice è utilizzare DataBinder .Eval da System.Web.UI:

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

Altri suggerimenti

Ho scritto un progetto open source, Dynamic Expresso , che può convertire espressioni di testo scritte usando un Sintassi C # in delegati (o albero delle espressioni). Le espressioni vengono analizzate e trasformate in Alberi delle espressioni senza utilizzare la compilazione o la riflessione.

Puoi scrivere qualcosa del tipo:

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

Il mio lavoro si basa sull'articolo di Scott Gu http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic- query-library.aspx .

In futuro (intorno al 5.0), il compilatore "come servizio" potrebbe essere in grado di farlo. In realtà, potresti essere in grado di fare molto di tutto questo ora con " mono " (vedi CsharpRepl e Mono.CSharp - tuttavia, mi aspetto che sarà necessario conoscere molto di più sul contesto per poter utilizzare local variabili ecc. in Valuta ) - ma non esiste alcun supporto per questo nell'attuale offerta MS .NET.

Per ora, dovresti fare qualcosa di simile a quello che fa molto del codice di associazione dei dati ... dividerlo per token come ". " e usa la riflessione. A rigor di termini, il codice di associazione utilizza in realtà TypeDescriptor / PropertyDescriptor anziché la riflessione diretta, ma l'effetto è lo stesso.

Sebbene abbia un approccio un po 'pesante, puoi usare CodeDom di C # per emettere un nuovo nuovo assembly che contiene un metodo con solo quella riga di codice.

Lo ammetto, molto più pesante di alcuni degli altri suggerimenti, lo ammetto, ma d'altra parte lasci che il parser C # esegua il sollevamento pesante, quindi dovrebbe essere in grado di gestire tutto ciò che gli passi finché è C # valido.

Se segui tale percorso, devi anche assicurarti di poter scaricare nuovamente l'assembly emesso, quindi potrebbe essere necessario creare e scaricare AppDomain.

Ho implementato e utilizzato con successo la tecnica sopra descritta. D'altra parte, se è possibile utilizzare un DynamicMethod sarebbe molto più leggero. Tuttavia, non ho mai provato questo approccio, quindi non posso dire se puoi implementare il corpo di un DynamicMethod usando i letterali C #.

In realtà, la valutazione dell'espressione e la funzionalità del motore delle regole di Windows Workflow Foundation possono fare queste cose. Vedi Introduzione al motore delle regole di Windows Workflow Foundation .

Una cosa interessante di questi componenti è che sono stati progettati in modo da poter ospitare i componenti in fase di progettazione nelle proprie applicazioni per progettare serie di regole e / o espressioni che operano nel contesto delle proprie classi personalizzate. Ad esempio, gli diresti di progettare un'espressione contro "myObject", e saprebbe che c'è un primo membro che ha un secondo membro che ha un indicizzatore che produce un tipo che ha una proprietà text. È possibile mantenere le espressioni e le regole come XML e rileggerle in fase di esecuzione, senza la necessità di utilizzare il designer in fase di esecuzione.

In particolare, vedi Esempio di toolkit di regole esterne .

Sfortunatamente, C # non ha strutture native per fare esattamente quello che stai chiedendo.

Tuttavia, il mio programma eval C # consente di valutare il codice C #. Fornisce la valutazione del codice C # in fase di runtime e supporta molte istruzioni C #, incluse espressioni come " myobject.firstMember.secondMember [3] .text " ;. In realtà, questo codice è utilizzabile in qualsiasi progetto .NET, tuttavia, è limitato all'uso della sintassi C #. Dai un'occhiata al mio sito web, http://csharp-eval.com , per ulteriori dettagli.

Puoi sempre provare il mio programma C # Eval leggero. Compila un sottoinsieme sostanziale del linguaggio C # in metodi dinamici. Dettagli completi sul mio repository GitHub DavidWynne / CSharpEval

AFAIK non esiste una funzione Eval integrata. Dovrai seguire il modo Regex + Reflection. Penso anche che Visual Studio stia facendo lo stesso.

Ecco qualcosa di simile che sto usando per trovare proprietà annidate in modo dinamico .. dovresti aggiungere la logica per gli indicizzatori ... e qualche controllo extra ... sto rilevando null / errori nel mio metodo di chiamata ...

  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;
  }
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top