2016-05-17 21 views
1

Ich habe dies sehr vereinfacht, um zum Kern des Problems zu kommen:Code inline auswerten (oder mit Reflektion)

Ich habe ein Steuerelement, das Eigenschaften benötigt bevölkert. Leider sitzen die Werte alle in CodeDom.CodeStatements.

So fischen Ich habe buchstäblich für die Werte von Code wie folgt verwendet:

static string GenerateCode(CodeStatementCollection statements, Control control) 
     { 
     var writer = new StringWriter(); 

     var compiler = new CSharpCodeProvider(); 

     foreach (CodeStatement statement in statements) 
     { 
      var codeAssignStatement = statement as System.CodeDom.CodeAssignStatement; 

      var left = codeAssignStatement?.Left as System.CodeDom.CodePropertyReferenceExpression; 

      if (left == null) 
      { 
       continue; 
      } 

      var right = codeAssignStatement.Right as System.CodeDom.CodeObjectCreateExpression; 

      if (right == null) 
      { 
       continue; 
      } 

      var expressionWriter = new StringWriter(); 
      compiler.GenerateCodeFromExpression(right,expressionWriter,null); 
      var expression = expressionWriter.ToString(); 

      control.SetPropertyValue(left.PropertyName, expression); 

      compiler.GenerateCodeFromStatement(statement, writer, null); 

     } 

     return writer.ToString(); 
     } 

Beachten Sie, dass der Code Reflexion verwendet, ist SetPropertyValue eigentlich eine Erweiterung Methode:

public static void SetPropertyValue(this object obj, string propName, object value) 
     { 
     obj.GetType().GetProperty(propName).SetValue(obj, value, null); 
     } 

Aber diese funktioniert nur, wenn der Wert ein Literalwert und kein Ausdruck ist.

Zur Laufzeit, was ich bekomme von der CodeDom-Anweisung ist ein Ausdruck, auch das Steuerelement ist eine Schaltfläche.

Button.Location = Neuer System.Drawing.Point (12,12);

So in dem obigen Codebeispiel Ausdruck = „New System.Drawing.Point (12,12)“

Nun will ich nicht durch eine Reihe von laufen zu haben, wenn Aussagen zum ersten Bestimmen Sie den Typ.

Ist es möglich, mithilfe von Reflektion eine Eigenschaft basierend auf einem Ausdruck festzulegen?

Wenn nicht, ist es möglich, eine Art von Eval-Funktion in .net zu verwenden, um dies zu entfernen?

Antwort

2

Um Code aus einem Skript zu erstellen, müssen Sie die Methode dynamisch kompilieren.

Das erste, was Sie tun müssten, ist die Methode in eine MethodInfo kompilieren. Sie können eine Methode erstellen, um dies zu erreichen.

Sobald Sie dies getan haben, können Sie es wie folgt verwenden.

var script = "public class Methods{public static System.Drawing.Point DoSomething(){return new System.Drawing.Point(12, 12);}}"; 

var method = CreateMethodInfo(script, "Methods", "DoSomething"); 

Jetzt, wo method Variable hält Ihre MethodInfo, so brauchen Sie nur um es aufzurufen.

Button.Location = (Point)method.Invoke(null, null); 
+0

Sie sind schlau! Das hat perfekt funktioniert. Vielen Dank! –

0

Ich denke, Sie können LINQ Ausdruck versuchen. https://msdn.microsoft.com/en-us/library/bb335710(v=vs.110).aspx

Ändern Sie folgende Methode mögen:

public static void SetPropertyValue(this object obj, string propName, Expression<Func<T, object>> value) 

konfigurieren und kompilieren die Delegatfunktion in Ausdruck und rufen Sie es in Ihrem SetPropertyValue().