Laden...

C# in C# ausführen

Erstellt von Basster vor 19 Jahren Letzter Beitrag vor 19 Jahren 8.238 Views
B
Basster Themenstarter:in
44 Beiträge seit 2004
vor 19 Jahren
C# in C# ausführen

Moin,

ich habe da mal eine Frage:

Kann man C# Code aus einem String auch irgendwie ausführen lassen?

Suche etwas vergleichbar mit eval() in JavaScript oder sp_execsql in T-SQL

R
51 Beiträge seit 2005
vor 19 Jahren

Hallo Basster,

ich verstehe dich so, dass du C# Quellcode zur Laufzeit eines Programms hast, diesen kompilieren und dann ausführen möchtest.

Hierfür kannst du den Namespace System.CodeDom verwenden. Dieser bietet dir Klassen, um Quellcode zur Laufzeit zu kompilieren.

Du kannst so z.B. eine Klasse, welche in C# Quellcode vorliegt zur Laufzeit kompilieren und dann beliebig Instanzen der Klasse erzeugen.

  • Rene
1.549 Beiträge seit 2004
vor 19 Jahren

Muss dan nicht das SDK Installiert sein??

Wir Arbeiten eigendlich nicht wir nehmen nur das geld

49.485 Beiträge seit 2005
vor 19 Jahren

Hallo S.H.-Teichhof,

das würde mich arg wundern. Man benutzt ja nicht den Compiler, sondern Klassen, die kompilieren können.

herbivore

R
51 Beiträge seit 2005
vor 19 Jahren

Ich denke auch, dass das Framework ausreichen sollte.

Man kann sich ja seinen eigenen Compiler aus den CodeDom-Klassen bauen.
Der C#-Compiler nutzt bestimmt auch diese Klassen und bietet Zugriff darauf über die Kommandozeile.

  • Rene
_
416 Beiträge seit 2005
vor 19 Jahren

Hallo Basster

hier und hier sind mal 2 Beispiele dafür was hier schon vorgeschlagen wurde. Letzteres hab ich auch schon selbst ausprobiert und es funktioniert wunderbar.

@thema sdk oder nicht sdk
Imho wird der Compiler (csc.exe) auch schon mit dem normalen Framework installiert. Ich denke also eher das die CodeDom-Klassen diesen benutzen (nicht andersrum 🙂 )
Daher seh ich auch keinen Grund warum das SDK benötigt werden sollte.

J
60 Beiträge seit 2004
vor 19 Jahren

Wie die leute bereits erwähnt haben, funktioniert das einwandfrei, auch mit normalen framework.

Ich entwickle hier eine Software, in welcher user scripte schreiben, die dann von uns ausgeführt werden, ich darf dir leider nicht den ganzen quellcode geben aber ein bischen beispiel kann ja sein:
Als aller ersten einfach mal eine simple klasse defenieren, am besten wäre im temp verzeichnis, ich nehme hier mal c::


StreamWriter writ = new StreamWriter("C:\\MyClass.cs");
//importierte Namespaces
rit.WriteLine(string.Format("using System;"));
//namespace der klasse
writ.WriteLine(string.Format("namespace MyNameSpace"));
//inerhalb des namespaces
writ.WriteLine("{");
//Klasse defenieren
writ.WriteLine(string.Format("public class {0}:{1}",MyClass","object");
//inerhalb der class
writ.WriteLine("{");
//die einzelnenn members schreiben
writ.WriteLine("public void DoSomeThing()");
writ.WriteLine("{");
writ.WriteLine("Console.WriteLine("Test");
writ.WriteLine("}");
writ.WriteLine("}");
writ.WriteLine("}");
writ.Close();

Nach dem wir den Code haben muss der Compiler generiert werden


//den code provider compiler und compilerparamenter erstellen
CSharpCodeProvider cscp = new CSharpCodeProvider();
CompilerParameters compparams = new CompilerParameters();
compparams.OutputAssembly="C:\MyDll.dll";
compparams.GenerateInMemory = false;
compparams.GenerateExecutable = false;
ICodeCompiler cscompiler = cscp.CreateCompiler();
compparams.ReferencedAssemblies.Add("System.dll");

//compelieren den ganzen mist
CompilerResults res = cscompiler.CompileAssemblyFromFileBatch(compparams,new file[]{"C:\\MyClass.cs"});

In res stehen jetzt die evtl fehler die aufgetreten sein sollten.

Das schwierige ist das verwenden der klasse, dazu braucht mal "Eigentlich" reflektion. Damits einfach wird solltest du ein interface in deiner application defenieren, dieses oben unter referenced assemblys hinzufügen, und die klasse dieses implementieren lassen.

Folgend geh ich mal davon aus du hast ein Interface MyInterface defeniert, mit der Funktion void DoSomeThing(), die klasse implementiert diese und hat einen public defaultconstruktor.

Das compelierte Assembly must du erstmal laden, sollte es kein problem sein, das das dll file gelockt wird(keine schreib berechtigung mehr auf die datei) kannst du

Assembly.Load("C:\MyDll.dll"); verwenden, im meinen fall war das nicht aktzeptabel, daher habe ich das über ein byte[] geregelt, benötigter namespace ist System.Reflection, System.IO:


FileStream stream = new FileStream("C:\\MyDll.dll",FileMode.Open);
byte[] rawAssembly = new byte[stream.Length];
stream.Read(rawAssembly,0,rawAssembly.Length);
stream.Close();
Assembly loaded =  Assembly.Load(rawAssembly);
Type wanntetType = this.assembly.GetType("MyNameSpace.MyClass",true);
object createted = System.Activator.CreateInstance(wanntetType,new object[0]);
MyInterface complete = created as MyInterface;
complete.DoSomeThing();

So, weiß das ist nicht ausführlich, muste auch viel umschreiben damit es etwas "einfacher" ist, sollte so aber prinzipiel funktionieren. Hoffe auf jedenfall eine hilfe gewesen zu sein 😉

lg

Ben

Das wirklich freie C# Buch für Programmieranfänger auf Wikibooks, auch du kannst helfen 😉

D
124 Beiträge seit 2005
vor 19 Jahren

Hallo Just-Ben,

das Laden der Assembly kannst du dir eigentlich sparen, da du über das "CompilerResult"-Objekt auf die kompilierte Assembly zugreifen kannst,
über CompilerResults.CompiledAssembly

Mfg

J
60 Beiträge seit 2004
vor 19 Jahren

nur wenn GenerateInMemory auf true gestellt wird. das war in dem beispiel nicht der fall, und macht in meiner anwendung sinn 😉

Das wirklich freie C# Buch für Programmieranfänger auf Wikibooks, auch du kannst helfen 😉