Laden...

code zur laufzeit kompilieren [und ausführen]?

Erstellt von jase vor 15 Jahren Letzter Beitrag vor 15 Jahren 2.275 Views
J
jase Themenstarter:in
39 Beiträge seit 2007
vor 15 Jahren
code zur laufzeit kompilieren [und ausführen]?

guten abend,

ich wuerde gerne wissen wie es moeglich ist ein c# programm zu erstellen, welches sourcecode "just in time" kompilieren kann.
konkret geht es um das erstellen eines skript generators, der die erstellten skripte auch starten soll.

kann mir wer ein paar tipps geben?

danke,
jan

2.891 Beiträge seit 2004
vor 15 Jahren

Hallo jase,

Das .NET-Framework bietet zwei verschiedene Alternativen, um eigene Typen zur Laufzeit zu erstellen:1.Das Erzeugen einer Assembly durch Kompilieren von Quelltext mithilfe einer ICodeCompiler-Implementierung (z.B. ) für eine konkrete .NET-Sprache, die den benutzerdefinierten Typ enthält.
Link: Generieren von Quellcode und Kompilieren eines Programms aus einem CodeDOM-Diagramm 1.Mit Hilfe von Funktionalitäten aus dem Namensraum System.Reflection.Emit wird MSIL-Code direkt erzeugt. Dabei werden assemblerähnliche MSIL-Befehle zusammengestellt und mit Metainformationen kombiniert.
Link: [Artikel] Reflection und Metaprogrammierung

Gruß,
dN!3L

J
jase Themenstarter:in
39 Beiträge seit 2007
vor 15 Jahren

danke!

ist eine der anderen methode vorzuziehen?

gruss,
jan

Gelöschter Account
vor 15 Jahren

aus performancetechnischen gründen und aus sicht vom handling ist nr.1 vorzuziehen.

3.971 Beiträge seit 2006
vor 15 Jahren

ist eine der anderen methode vorzuziehen?

Was stellst du dir denn konkret anders vor?

Alternativ könntest du beispielsweise auch eine neue Quellcode-Datei schreiben (temp-Ordner) und anschließend csc.exe aufrufen und die neue Bibliothek in eine neue AppDomain laden und entsprechend benutzen.

Es gibt 3 Arten von Menschen, die die bis 3 zählen können und die, die es nicht können...

49.485 Beiträge seit 2005
vor 15 Jahren

Hallo kleines_eichhoernchen,

Was stellst du dir denn konkret anders vor?

es ging nicht um einen dritten Weg, sondern welcher von den beiden vorgeschlagenen vorzuziehen ist.

herbivore

J
jase Themenstarter:in
39 Beiträge seit 2007
vor 15 Jahren

ein generiertes skript sieht zbsp wie folgt aus:


while(true)
{
Led[0] = 25;
Led[2] = 0;
Led[3] = 25;
Led[5] = 25;
WriteToDevice(Data);
for(i=0; i <= 25; i++)
{
Led[0] = (byte)(25-i);
Led[6] = (byte)(25-i);
WriteToDevice(Data);
}
System.Threading.Thread.Sleep(2000);
Status = 25;
WriteToDevice(Data);
Status = 0;
WriteToDevice(Data);
}

@herbivore
wenn es auch eine dritte ernstzunehmende loesung gibt, wieso diese nicht auch beachten?

mfg,
jan

3.971 Beiträge seit 2006
vor 15 Jahren

Allerdings musst du die Schleife zuvor in eine Funktion und Klasse kaspeln. Am besten innerhalb der Klasse noch Eigeschaften für Argumente und Rückgabewerte definieren.

Weiterhin vermeide bitte Thread.Sleep und verwende dafür besser einen geeigneten Timer, beispielsweise System.Threading.Timer oder System.Windows.Forms.Timer.

Es gibt 3 Arten von Menschen, die die bis 3 zählen können und die, die es nicht können...

J
jase Themenstarter:in
39 Beiträge seit 2007
vor 15 Jahren

ok, danke.

was spricht denn gegen Thread.Sleep?

49.485 Beiträge seit 2005
vor 15 Jahren

Hallo jase,

(Thread.)Sleep ist schon ei relativ altes Konstrukt und wurde in vielen Anwendungsbereichen durch Timer abgelöst. Es gibt natürlich einige wenige Fällen, in denen Thread.Sleep weiterhin Sinn macht. Deine Schleife macht jedoch den Eindruck, dass eine Aktion zu wiederkehrenden Zeitpunkten ausgeführt werden soll. Das ist voll die Domäne von Timern.

herbivore

J
jase Themenstarter:in
39 Beiträge seit 2007
vor 15 Jahren

Das Erzeugen einer Assembly durch Kompilieren von Quelltext mithilfe einer
>
-Implementierung (z.B. ) für eine konkrete .NET-Sprache, die den benutzerdefinierten Typ enthält.
Link:
>

das beispiel hab ich mir angeschaut - wenn ich das aber richtig verstehe wird ein komplett neues programm generiert und in eine neue .exe gepackt.
ich wuerde aber gerne den code, den ich aus der source datei lade compilieren und dann in meinem bestehenden programm verwenden.
ich stelle mir das beispielsweise so vor, dass ich auf einen button klicke: der code wird aus der datei geladen, kompiliert und direkt ausgefuehrt - ohne umweg via eines komplett neuen programms.

ist das auch moeglich?

gruss,
jan

49.485 Beiträge seit 2005
vor 15 Jahren

Hallo jase,

kompiliere nicht in eine EXE, sondern in eine DLL. Die kannst du dann mit Assembly.Load o.ä. in das laufende Programm einbinden.

herbivore

J
jase Themenstarter:in
39 Beiträge seit 2007
vor 15 Jahren

Hallo jase,

kompiliere nicht in eine EXE, sondern in eine DLL. Die kannst du dann mit Assembly.Load o.ä. in das laufende Programm einbinden.

herbivore

ah ok:


  // Generate an executable instead of 
    // a class library.
    cp.GenerateExecutable = true;

ich setze das einfach auf false, generiere eine dll und lade diese dann mittels assembly.load zur laufzeit ein, danke!

O
778 Beiträge seit 2007
vor 15 Jahren

aus performancetechnischen gründen und aus sicht vom handling ist nr.1 vorzuziehen.

Aus performancetechnischen Gründen? Handling hast du ganz klar meine Zustimmung, aber Performance? Ich mein, CodeDOM ist als DOM mit ziemlicher Sicherheit speicherintensiver und muss nicht mehr in irgendeiner Art und Weise kompiliert werden, sollte also imho schneller sein.

Das soll nicht heißen, dass ich auf Reflection.Emit zurückgreifen würde, weil man muss schon sehr genau wissen, was man tut, um IL einfach so runterschreiben zu können.

Gelöschter Account
vor 15 Jahren

das aufrufen der methoden über reflection ist langsam.

2.891 Beiträge seit 2004
vor 15 Jahren

das aufrufen der methoden über reflection ist langsam.

Die Rede ist doch aber von Reflection.Emit. Da wird ja IL-Code direkt erzeugt.
Sollte zudem schneller als CodeDOM sein, weil ja Scanning, Parsing, TypeChecking etc. entfallen (weil ja direkt IL erzeugt wird).

Gruß
dN!3L

3.971 Beiträge seit 2006
vor 15 Jahren

lade diese dann mittels assembly.load zur laufzeit ein

Lade die Assembly nicht unbedingt in die aktuelle AppDomain, sondern erstelle eine neue. Nach der Verwendung der generierten Assembly kannst du anschließend die Assembly/AppDomain wieder entladen.

Die seperate AppDomain ist vor allem dann wichtig, wenn mehrmals die Assembly neu generiert wird und anschließend geladen wird. Das wäre eine schönes Speicherleck. In .NET ist es nicht möglich einzelne Assemblies zu entladen.

Es gibt 3 Arten von Menschen, die die bis 3 zählen können und die, die es nicht können...

Gelöschter Account
vor 15 Jahren

Die Rede ist doch aber von Reflection.Emit. Da wird ja IL-Code direkt erzeugt.
Sollte zudem schneller als CodeDOM sein, weil ja Scanning, Parsing, TypeChecking etc. entfallen (weil ja direkt IL erzeugt wird).

das erzeugen mag ja schneller sein aber der aufruf der erstellen methode ist gähnend lahm.

F
10.010 Beiträge seit 2004
vor 15 Jahren

Wieso ist mit Emit erzeugter Code lahm?

Das kann ich nicht bestätigen.
Vielleicht machst Du ja etwas falsch, das es so ist.

Gelöschter Account
vor 15 Jahren

nicht der code ist lahm sonder das invoke.

F
10.010 Beiträge seit 2004
vor 15 Jahren

Wenn man per DynamicMethod eine Funktion erzeugt, und am schluss dann per
CreateDelegate eine Zeiger darauf erhält, ist das aufrufen der Funktion dann
genauso schnell, wie fertig kompilierter code des Compilers.

Wo ist da ein Invoke, und wo sollte das langsam sein?

2.891 Beiträge seit 2004
vor 15 Jahren

nicht der code ist lahm sonder das invoke.

Nein!? Es wird doch gar nicht mit Invoke gearbeitet. Nur weil da "Reflection" steht, heißt das nicht, dass Methoden auch mit Invoke() aufgerufen werden. Es werden halt nur Assemblies mit Regflection.Emit erstellt, die dann auch wie ganz normal geladen und ausgeführt werden können. Nix mit Invoke...!

EDIT: Einen Performanzvergleich zwischen Method.Invoke und DynamicMethod findest du übrigens hier.

Gruß,
dN!3L

4.207 Beiträge seit 2003
vor 15 Jahren

Was auch noch eine Möglichkeit wäre, ist RunSharp (http://sourceforge.net/projects/runsharp)

Wissensvermittler und Technologieberater
für .NET, Codequalität und agile Methoden

www.goloroden.de
www.des-eisbaeren-blog.de