| 

.NET C# Java Javascript Exception

2
Wie kann ich eine Methode aus einem C#-Code-String zur Laufzeit nutzen? Bonus: Mit und ohne dynamic Schlüsselwort?
News:
04.02.2011
KCT 937 1 8
6 Antworten
5
.Net Bietet einen Compiler den man zur Laufzeit benutzen kann alias CodeDomProvider.

Hier ein Beispielcode:
using System;
using System.CodeDom.Compiler;
using System.Reflection;
using System.Text;

namespace Code_zur_Laufzeit_erzeugen
{
class Program
{
static void Main(string[] args)
{
Console.Write("Enter text -> ");
string textInput = Console.ReadLine();

Assembly assembly = CompileCode(textInput);
object o = assembly.CreateInstance("gfoidl.Code.Test");
Type t = o.GetType();
MethodInfo mi = t.GetMethod("Ergebnis");
object result = mi.Invoke(o, new object[] { textInput });
Console.WriteLine(result);

Console.ReadKey();
}
//---------------------------------------------------------------------
public static Assembly CompileCode(string inputCode)
{
CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp");

CompilerParameters cp = new CompilerParameters();
cp.ReferencedAssemblies.Add("system.dll");
cp.CompilerOptions = "/t:library";
cp.GenerateInMemory = true;

StringBuilder sb = new StringBuilder();
sb.AppendLine(@"using System;");
sb.AppendLine(@"namespace gfoidl.Code{");
sb.AppendLine(@"public class Test{");
sb.AppendLine(@"public string Ergebnis(string input){");
sb.AppendLine(@"return input + ""\t"" + input;");
sb.AppendLine(@"}}}");

CompilerResults cr =
provider.CompileAssemblyFromSource(cp, sb.ToString());

if (cr.Errors.Count > 0)
{
Console.WriteLine(cr.Errors[0].ErrorText);
return null;
}

return cr.CompiledAssembly;
}
}
}

Quelle: http://dotnet-snippets.de/dns/kompilierung-zur-laufzeit-SID986.aspx
04.02.2011
Floyd 14,6k 3 9
2
Du kannst den Code zur Laufzeit compilen.

Dazu brauchst Du

using Microsoft.CSharp;
using System.CodeDom.Compiler;


Dann musst Du Dir eine Compiler Instanz erzeugen:

CSharpCodeProvider myCodeProvider = new CsharpCodeProvider();
CodeCompiler myCodeCompiler = myCodeProvider.CreateCompiler();


Mit diesem Compiler kann man dann wunderbarerweise auch compilen! :-)
Allerdings sollte man auch die Referenzen, die man normalerweise im Visual Studio mit den Project References bekannt gibt, auf eine etwas eigentümlich Art und Weise mitgeben, und zwar als String array dass die Assemblies (dlls) enthält :

String [] references = {"System.dll"};


Du musst Dir auch noch einen Namen für die Assembly ausdenken, die Du beim Compilen erzeugen willst - und Dich entscheiden, ob Du die Assembly auch als Datei schreiben willst oder nur In-Memory nutzen willst:

Dafür nutzen wir die Klasse CompilerParameters:
CompilerParameters parameter = 
new CompilerParameters(references, "MeineGenerierteAssembly.dll");

myCompilerParameters.GenerateExecutable = false;
myCompilerParameters.GenerateInMemory = true;


So... jetzt kann man schon compilen:
String meinCSharpCode = "namespace Foobar { .... }";
CompilerResults myCompilerResults =
myCodeCompiler.CompileAssemblyFromSource(parameter, meinCSharpCode)



Mit Reflection / dynamic kannst Du dann diese compilierten Klassen / etc. instanzieeren und nutzen und Methoden aufrufen.

Grüße
CRegenschein
04.02.2011
CRegenschein 645 2 9
1
Es gibt ein Snippet unter http://dotnet-snippets.de/dns/kompilierung-zur-laufzeit-SID986.aspx dazu. Das sollte dir weiterhelfen.

Da war schon einer schneller :-)
04.02.2011
chaos666 11 1
1
Wow seid ihr schnell. Besten Dank.
04.02.2011
KCT 937 1 8
1
Im obigen Beispiel wird eine Instanz der dll erzeugt, die erst beim Beenden der App wieder freigegeben wird. Bei Verwendung einer AppDomain für das PlugIn sind UserControl oder sonstiges bei Verwendung von WPF ausgeschlossen. Eine vernünftige Lösung dafür habe ich bisher noch nicht gefunden.

Jürgen
04.02.2011
0
Hi,
Das mit dem kompilieren ist ja kein Problem, aber wie funktioniert das am besten, wenn ich die erzeugte dll in dem kompilierenden Programm sofort nutzen (testen) möchte? Wenn etwas nicht so funktioniert, es abändern und neu testen will ohne das Programm neu zu starten - so als Art Plugin-Schnittstelle direkt aus der Anwendung heraus. Eine einmal referenzierte dll kann ich doch nicht einfach wieder entfernen, oder?

Gruß,
Jürgen
04.02.2011
Ist in dem oberen Beispiel doch abgebildet. Er ruft doch die Methode Ergebnis auf. Ansonsten schau dir das mal an:
http://codekicker.de/fragen/csharp-Assembly-Laufzeit-laden-assembly-laufzeit-laden-plug-in/672
Konstantin 04.02.2011

Stelle deine .net-Frage jetzt!
TOP TECHNOLOGIES CONSULTING GmbH