Wie kann ich C # -Code dynamisch auswerten?

  • Ich kann ein eval("something()"); ausführen, um den Code dynamisch in JavaScript auszuführen. Gibt es eine Möglichkeit für mich, dasselbe in C # zu tun?

    Ein Beispiel für das, was ich versuche, ist: Ich habe eine Integer-Variable (etwa i) und Ich habe mehrere Eigenschaften mit den Namen: "Property1", "Property2", "Property3" usw. Nun möchte ich einige Operationen an der Eigenschaft "Property i " ausführen, je nach dem Wert von i.

    Mit Javascript ist das ganz einfach. Gibt es eine Möglichkeit, dies mit C # zu tun?

    10 April 2018
    ScathChad Harrison
16 answers
  • Leider ist C # keine solche dynamische Sprache.

    Sie können jedoch eine C # -Quellcodedatei mit Klasse erstellen und alles, und führen Sie es über den CodeDom-Provider für C # aus, kompilieren Sie es in einer Assembly und führen Sie es dann aus.

    Dieser Forenbeitrag auf MSDN enthält eine Antwort mit einem Beispielcode die Seite etwas:
    eine anonyme Methode aus einem String erstellen?

    Ich würde kaum sagen, dass dies eine sehr gute Lösung ist, aber es ist trotzdem möglich.

    Welche Art von Code erwarten Sie in dieser Zeichenfolge? Handelt es sich um eine untergeordnete Menge gültigen Codes, beispielsweise um mathematische Ausdrücke, gibt es möglicherweise andere Alternativen.


    Bearbeiten : Nun, ich lerne, die Fragen zuerst gründlich zu lesen. Ja, das Nachdenken kann Ihnen hier helfen.

    Wenn Sie den String durch das; Um einzelne Eigenschaften abzurufen, können Sie den folgenden Code verwenden, um ein PropertyInfo-Objekt für eine bestimmte Eigenschaft für eine Klasse abzurufen, und dann dieses Objekt verwenden, um ein bestimmtes Objekt zu bearbeiten.

     String propName = "Text";
    PropertyInfo pi = someObject.GetType().GetProperty(propName);
    pi.SetValue(someObject, "New Value", new Object[0]);
     

    Link: PropertyInfo.SetValue-Methode

    24 March 2015
    Dan AtkinsonDmitry_F
  • Nicht wirklich. Sie können Reflection verwenden, um das zu erreichen, was Sie möchten, aber es ist nicht so einfach wie in Javascript. Wenn Sie beispielsweise das private Feld eines Objekts auf etwas festlegen möchten, können Sie diese Funktion verwenden:

     protected static void SetField(object o, string fieldName, object value)
    {
       FieldInfo field = o.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic);
       field.SetValue(o, value);
    }
     
    07 February 2016
    Markus SafarMHop
  • Verwenden der Roslyn-Skript-API (weitere Beispiele hier ):

     // add NuGet package 'Microsoft.CodeAnalysis.Scripting'
    using Microsoft.CodeAnalysis.CSharp.Scripting;
    
    await CSharpScript.EvaluateAsync("System.Math.Pow(2, 4)") // returns 16
     

    Sie können auch einen beliebigen Code ausführen:

     var script = await CSharpScript.RunAsync(@"
                    class MyClass
                    { 
                        public void Print() => System.Console.WriteLine(1);
                    }")
     

    Und verweisen Sie auf den Code, der in vorherigen Läufen generiert wurde:

     await script.ContinueWithAsync("new MyClass().Print();");
     
    23 June 2016
    Eli Arbel
  • Ich habe ein Open-Source-Projekt Dynamic Expresso geschrieben, das Textausdrücke konvertieren kann mit einer C # -Syntax in Delegaten (oder Ausdrucksbaum) geschrieben. Ausdrücke werden analysiert und in Ausdrucksbäume umgewandelt, ohne Kompilierung oder Reflektion zu verwenden.

    Sie können Folgendes schreiben:

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

    oder

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

    Meine Arbeit basiert auf Scott Gu Artikel http://weblogs.asp.net/scottgu/ Archiv / 2008/01/07 / dynamic-linq-part-1-using-the-linq-dynamische-query-library.aspx .

    07 February 2016
    Markus SafarMHop
  • All das würde auf jeden Fall funktionieren. Für dieses spezielle Problem würde ich wahrscheinlich etwas anders vorgehen. Vielleicht so etwas:

     class MyClass {
      public Point point1, point2, point3;
    
      private Point[] points;
    
      public MyClass() {
        //...
        this.points = new Point[] {point1, point2, point3};
      }
    
      public void DoSomethingWith(int i) {
        Point target = this.points[i+1];
        // do stuff to target
      }
    }
     

    Wenn Sie Muster wie dieses verwenden, müssen Sie darauf achten, dass Ihre Daten gespeichert werden als Referenz und nicht als Wert. Mit Primitiven also nicht. Sie müssen ihre großen aufgeblähten Klassenkollegen verwenden.

    Ich habe erkannt, dass das nicht genau die Frage ist, aber die Frage wurde ziemlich gut beantwortet und ich dachte, ein alternativer Ansatz könnte helfen.

    07 August 2008
    MojoFilter
  • Dies ist eine Eval-Funktion unter c #. Ich habe es verwendet, um anonyme Funktionen (Lambda-Ausdrücke) aus einer Zeichenfolge zu konvertieren. : //www.codeproject.com/KB/cs/evalcscode.aspx

     public static object Eval(string sCSCode) {
    
      CSharpCodeProvider c = new CSharpCodeProvider();
      ICodeCompiler icc = c.CreateCompiler();
      CompilerParameters cp = new CompilerParameters();
    
      cp.ReferencedAssemblies.Add("system.dll");
      cp.ReferencedAssemblies.Add("system.xml.dll");
      cp.ReferencedAssemblies.Add("system.data.dll");
      cp.ReferencedAssemblies.Add("system.windows.forms.dll");
      cp.ReferencedAssemblies.Add("system.drawing.dll");
    
      cp.CompilerOptions = "/t:library";
      cp.GenerateInMemory = true;
    
      StringBuilder sb = new StringBuilder("");
      sb.Append("using System;\n" );
      sb.Append("using System.Xml;\n");
      sb.Append("using System.Data;\n");
      sb.Append("using System.Data.SqlClient;\n");
      sb.Append("using System.Windows.Forms;\n");
      sb.Append("using System.Drawing;\n");
    
      sb.Append("namespace CSCodeEvaler{ \n");
      sb.Append("public class CSCodeEvaler{ \n");
      sb.Append("public object EvalCode(){\n");
      sb.Append("return "+sCSCode+"; \n");
      sb.Append("} \n");
      sb.Append("} \n");
      sb.Append("}\n");
    
      CompilerResults cr = icc.CompileAssemblyFromSource(cp, sb.ToString());
      if( cr.Errors.Count > 0 ){
          MessageBox.Show("ERROR: " + cr.Errors[0].ErrorText, 
             "Error evaluating cs code", MessageBoxButtons.OK, 
             MessageBoxIcon.Error );
          return null;
      }
    
      System.Reflection.Assembly a = cr.CompiledAssembly;
      object o = a.CreateInstance("CSCodeEvaler.CSCodeEvaler");
    
      Type t = o.GetType();
      MethodInfo mi = t.GetMethod("EvalCode");
    
      object s = mi.Invoke(o, null);
      return s;
    
    }
     
    24 December 2011
    Largo
  • Ich weiß jetzt nicht, ob Sie unbedingt C # -Anweisungen ausführen möchten, aber Sie können bereits Javascript-Anweisungen in C # 2.0 ausführen. Die Open-Source-Bibliothek Jint kann dies tun. Es ist ein Javascript-Interpreter für .NET. Übergeben Sie ein Javascript-Programm und es wird in Ihrer Anwendung ausgeführt. Sie können sogar ein C # -Objekt als Argumente übergeben und eine Automatisierung durchführen.

    Wenn Sie den Ausdruck nur für Ihre Eigenschaften auswerten möchten, versuchen Sie NCalc .

    14 October 2009
    Sébastien Ros - MSFT
  • Sie können Reflection verwenden, um die Eigenschaft abzurufen und aufzurufen. Etwas wie das:

     object result = theObject.GetType().GetProperty("Property" + i).GetValue(theObject, null);
     

    Das heißt, wenn das Objekt, das die Eigenschaft besitzt, "theObject" heißt :)

    07 August 2008
    David Wengier
  • Sie können auch einen Webbrowser implementieren und dann eine HTML-Datei laden, die Javascript enthält.

    Dann wählen Sie in diesem Browser die Methode document.InvokeScript. Der Rückgabewert der eval-Funktion kann abgefangen und in alles umgewandelt werden, was Sie benötigen.

    Ich habe dies in mehreren Projekten gemacht und es funktioniert einwandfrei.

    Hoffe es hilft

    25 November 2011
    OtielMathias Lykkegaard Lorenzen
  • Sie können dies mit einer Prototypfunktion tun:

     void something(int i, string P1) {
        something(i, P1, String.Empty);
    }
    
    void something(int i, string P1, string P2) {
        something(i, P1, P2, String.Empty);
    }
    
    void something(int i, string P1, string P2, string P3) {
        something(i, P1, P2, P3, String.Empty);
    }
     

    und so weiter ...

    07 August 2008
    GateKiller