Sonntag, Dezember 8, 2019

Analyse von C# – code (als string) und zusätzliche Methoden einfügen

Habe ich eine C# – app an der ich arbeite, lädt es den code aus der Ferne, und dann läuft es (aus Gründen der Argumentation, können Sie davon ausgehen, das app ist sicher).

Der code ist C#, aber es ist geschickt, als XML-Dokument analysiert wird als ein string, und dann kompiliert und ausgeführt.

Nun, was ich tun möchte – und bin mit ein bisschen mehr Mühe, als ich erwartet hatte – ist in der Lage zu analysieren, das gesamte Dokument, und vor dem kompilieren, fügen Sie zusätzliche Befehle nach jeder line Ausführung.

Betrachten Sie beispielsweise den code:

using System;
using System.Collections.Generic;
using System.Linq;

namespace MyCode
{
    static class MyProg
    {
        static void Run()
        {
            int i = 0;
            i++;

            Log(i);
        }
    }
}

Was ich möchte, nach dem Parsen ist etwas mehr wie:

using System;
using System.Collections.Generic;
using System.Linq;

namespace MyCode
{
    static class MyProg
    {
        static void Run()
        {
            int i = 0;
            MyAdditionalMethod();
            i++;
            MyAdditionalMethod();

            Log(i);
            MyAdditionalMethod();
        }
    }
}

Beachten Sie die offensichtliche Fallstricke – ich kann nicht nur haben Sie nach jedem Semikolon, weil das nicht funktionieren würde, in einem getter/setter, d.h.:

Umwandeln:

public string MyString { get; set; }

Zu:

public string MyString { get; MyAdditionalMethod(); set; MyAdditionalMethod(); }

scheitern würden. Wie würde die Klasse-level-Deklarationen, Anweisungen, etc. Auch gibt es eine Reihe von Fällen, in denen konnte ich auch in MyAdditionalMethod() nach geschweiften Klammern, wie in der Delegierten unmittelbar nach der if-Anweisungen, oder der Methode, Erklärungen, etc.

So, was ich gesucht habe in CodeDOM, und dieses sieht wie es könnte eine Lösung sein, aber es ist hart, um herauszufinden, wo zu beginnen. Ich bin sonst versuchen zu analysieren, die ganze Sache, und erstellen Sie eine Struktur, die ich analysieren kann durch – aber das ist ein wenig schwierig sein, unter Berücksichtigung der Anzahl der Fälle, die ich beachten muss.

Kennt jemand andere Lösungen, die es gibt?

  • „Der code ist C#, aber es ist geschickt, als XML-Dokument analysiert, wie eine Zeichenfolge“ — abgesehen, wie komisch das alles klingt, können wir ein Beispiel der XML? Vielleicht können Sie injizieren Ihre Methoden, bevor es analysiert in einem string.
  • Ich keine Kontrolle über die XML-Dokument, so kann ich nicht Spritzen etwas, bis es ankommt und ausgewertet. Die XML beinhaltet nur den code als text ein element – ie. <Code>using System.IO; namespace MyApp { public class myClass {… </Code>
InformationsquelleAutor AlishahNovin | 2011-02-14

5 Kommentare

  1. 7

    Gibt es ein paar C# – Parser gibt, würde ich empfehlen, mit so etwas aus Mono-oder SharpDevelop als Sie sollten aktuell sein. Ich hatte einen gehen mit NRefactory von SharpDevelop, wenn Sie download die Quelle für SharpDevelop gibt es eine demo und einige UnitTests sind ein gutes intro zu seiner Verwendung.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using ICSharpCode.NRefactory;
    using System.IO;
    using ICSharpCode.NRefactory.Ast;
    using ICSharpCode.NRefactory.Visitors;
    using ICSharpCode.NRefactory.PrettyPrinter;
    namespace Parse
    {
    class Program
    {
    static void Main(string[] args)
    {
    string code = @"using System;
    using System.Collections.Generic;
    using System.Linq;
    namespace MyCode
    {
    static class MyProg
    {
    static void Run()
    {
    int i = 0;
    i++;
    Log(i);
    }
    }
    }
    ";
    IParser p = ParserFactory.CreateParser(SupportedLanguage.CSharp, new StringReader(code));
    p.Parse();
    //Output Original
    CSharpOutputVisitor output = new CSharpOutputVisitor();
    output.VisitCompilationUnit(p.CompilationUnit, null);
    Console.Write(output.Text);
    //Add custom method calls
    AddMethodVisitor v = new AddMethodVisitor();
    v.VisitCompilationUnit(p.CompilationUnit, null);
    v.AddMethodCalls();
    output = new CSharpOutputVisitor();
    output.VisitCompilationUnit(p.CompilationUnit, null);
    //Output result
    Console.Write(output.Text);
    Console.ReadLine();
    }
    }
    //The vistor adds method calls after visiting by storing the nodes in a dictionary. 
    public class AddMethodVisitor : ConvertVisitorBase
    {
    private IdentifierExpression member = new IdentifierExpression("MyAdditionalMethod");
    private Dictionary<INode, INode> expressions = new Dictionary<INode, INode>();
    private void AddNode(INode original)
    {
    expressions.Add(original, new ExpressionStatement(new InvocationExpression(member)));
    }
    public override object VisitExpressionStatement(ExpressionStatement expressionStatement, object data)
    {
    AddNode(expressionStatement);
    return base.VisitExpressionStatement(expressionStatement, data);
    }
    public override object VisitLocalVariableDeclaration(LocalVariableDeclaration localVariableDeclaration, object data)
    {
    AddNode(localVariableDeclaration);
    return base.VisitLocalVariableDeclaration(localVariableDeclaration, data);
    }
    public void AddMethodCalls()
    {
    foreach (var e in expressions)
    {
    InsertAfterSibling(e.Key, e.Value);
    }
    }
    }
    }

    Werden Sie brauchen, um zu verbessern, die Besucher zu Griff mehr Fälle, aber es ist ein guter Anfang.

    Alternativ können Sie kompilieren Sie das original und einige IL manipulation mit Cecil oder versuchen, einige AOP-Bibliothek, wie PostSharp. Schließlich kann man sich in der .NET-Profiling-API.

  2. 3

    Könnten Sie verwenden ein source-to-source-transformation-Programm-system. Ein solches Werkzeug analysiert den code, baut und ASTs, können Sie die Transformationen anzuwenden, und dann regeneriert text aus dem AST. Was macht ein source-to-source-system ist nett, dass Sie schreiben können, die Transformationen in Bezug auf die Quell-Sprache-syntax anstatt der fraktalen detail der AST, wodurch Sie weit einfacher zu schreiben und zu verstehen, später.

    Was Sie wollen, zu tun wäre, modelliert durch eine ziemlich einfache Programm-transformation
    mit unserem DMS Software Reengineering Toolkit:

    rule insert_post_statement_call(s: stmt): stmt -> stmt =
    " \s " -> " { \s ; MyAdditionalMethod();   }";

    Diese Regel nicht ein „text“ substitution; es ist vielmehr analysiert der parser, der die Prozesse der Ziel-code, und so in der Tat es stellt zwei ASTs, einer linken – und rechten Seite (getrennt durch „->“ syntax. Die Zitate sind nicht string-Anführungszeichen; Sie Anführungszeichen, um die Ziel-Sprache, – syntax, es zu unterscheiden sich von der syntax des Regel-die Sprache selbst. Was innerhalb der Anführungszeichen ist der target-Sprache (z.B. C#) – text mit escapes wie \s, die gesamte Sprach-Elemente (in diesem Fall vorgegeben, nach der die target-Sprache (z.B. C#) – Grammatik. Die linke Seite sagt, „match any-Anweisung s“, da s ist definiert als eine „stmt“ in der Grammatik. Die Rechte Seite sagt, „ersetzen Sie die Anweisung durch einen block mit der ursprünglichen Aussage \s, und den neuen code eingefügt“. Dies alles geschieht in Bezug auf die syntax-Bäume mit der Grammatik als Leitfaden; es kann nicht gelten, das zu transformieren, um alles, was nicht eine Erklärung. [Der Grund für das umschreiben der Erklärung, wie ein block, ist da die Rechte Seite ist gültig, wenn Aussagen gültig sind, gehen Sie überprüfen Sie Ihre Grammatik.]

    Als eine praktische Sache, müssen Sie Regeln schreiben, die zur Behandlung anderer besonderer Fälle, aber das ist meist schreiben mehrere Regeln. Sie müssen auch das Paket parser/Transformator/prettyprinter als bundle, das erfordert einige verfahrensmäßige Leim. Dies ist immer noch weit einfacher als zu versuchen, code zu schreiben, um zuverlässig klettern nach oben und unten der Baum, passend zu den Knoten und dann smashing diesen Knoten zu bekommen, was Sie wollen. Besser, wenn Sie Ihre Grammatik (immer) angepasst werden muss, sind die rewrite-Regeln werden erneut analysiert nach der Neufassung des Grammatik-und immer noch funktionieren; was procedural Baum klettern Sie dadurch fast schon garantiert zu brechen.

    Wie Sie schreiben, mehr und mehr Transformationen, diese Fähigkeit wird mehr und mehr wertvoll. Und wenn Sie erfolgreich sind, mit einer kleinen Anzahl von Transformationen, indem mehr interessant wird schnell.

    Sehen dieses technische Papier für eine Gründliche Diskussion darüber, wie die DMS funktioniert und wie es angewendet wird Instrumentierung Transformationen, wie Sie wollen, zu tun, in echten Werkzeugen. Dieses Papier beschreibt die grundlegenden Ideen, die hinter dem test-coverage-tools verkauft von Semantic Designs.

    • Dies scheint nur eine Anzeige für ein Produkt, das Sie wahrscheinlich nicht brauchen. Die .Net framework bietet einfache Klassen für on-the-fly compilation
    • aus dem OP: „kennt jemand andere Lösungen, die es gibt?“ Vielen Dank für das ding.
  3. 1

    Für die Analyse, die Sie nutzen könnten CSharpCodeProvider-Klasse’s Parse() .

    • Ich denke, dass dies eine NotImplementedException.
    • Falsch. Die base-Klasse (CodeDomProvider) NotImplementedException wirft. Die Methode überschrieben wird, die von abgeleiteten Klassen (wie CSharpCodeProvider) und deshalb wirft es keine solche Ausnahme.
    • Wo haben Sie gesehen, dass CSharpCodeProvider überschreibt CreateParser oder Analysieren?

Kostenlose Online-Tests

Letzte Fragen

Tun ItemView löst Blase?

Ich habe eine CompositeView für eine Tabelle. Ich habe Trigger-set in der Kind-ItemView für jede Zeile... var TableRow = Marionette.ItemView.extend({ tagName:...

Wie kann ich untersuchen, WCF was 400 bad request über GET?

Die folgenden WCF-endpoint funktioniert gut mit dem WCF test client: AssetList ListFlaggedAssets(short processCode, string platform, string endpoint = "null", string portalId = "null", int...

Bei der Verwendung von UUIDs, sollte ich auch mit AUTO_INCREMENT?

Wir bauen eine neue web-app, die eine offline-iPad - /Android-app-version auf einer Reihe von lokalen Geräten, die Einsätze mit neuen Daten. Als solche benötigen...

Actionscript-Objekt, das verschiedene Eigenschaften

Wie kann ich die Anzahl der Eigenschaften in einer generischen Actionscript-Objekt? (Wie die Array-Länge) InformationsquelleAutor Fragsworth | 2011-01-15

Wie plot mehrere Graphen und nutzen Sie die Navigations-Taste im [matplotlib]

Die neueste version von matplotlib erstellt automatisch Navigations-buttons unter den graph. Aber die Beispiele, die ich finden alles im Internet zeigen, wie erstellen Sie...