Ich möchte Monos Compiler als einen Dienst von meiner regulären .NET 3.5-Anwendung verbrauchen.Mono-Compiler als Dienst (MCS)
Ich habe die neuesten Bits (2.6.7) heruntergeladen, erstellt eine einfache Konsolenanwendung in Visual Studio und referenzierte die Mono.CSharp dll.
Dann in meiner Konsolenanwendung (gerade jetzt online einer Probe):
Evaluator.Run("using System; using System.Linq;");
bool ress;
object res;
Evaluator.Evaluate(
"from x in System.IO.Directory.GetFiles (\"C:\\\") select x;",
out res, out ress);
foreach (var v in (IEnumerable)res)
{
Console.Write(v);
Console.Write(' ');
}
Dies löst eine Ausnahme bei Evaluator.Run (die erste Zeile):
Illegal enum value: 2049.
Parameter name: access
Dies liegt daran, Die DLL wurde mit Mono.exe und nicht mit csc.exe kompiliert, glaube ich.
Ich habe versucht, die Mono.CSharp dll direkt von http://tirania.org/blog/archive/2010/Apr-27.html in der Datei demo-repl.zip ... und das wirft keine Ausnahme ... Allerdings die out-Parameter (res) nach dem Aufruf von Evaluator.Evaluate ist null ... also bin ich mir nicht sicher, was schief läuft. Es wird keine Ausnahme geworfen ...
Also, ich würde gerne herausfinden, warum die DLL, die ich von der demo-repl.zip heruntergeladen habe, Null zurückgibt.
EDIT: Ich habe herausgefunden, warum es Null zurückgibt. Aus irgendeinem Grund scheint der Compiler den System.Linq-Namespace nicht aufzunehmen ... obwohl ich nicht sagen kann, warum ... Wenn ich nur "System.IO.Directory.GetFiles (\" C: \\ ")", es funktioniert gut.
UPDATE: Es scheint auf jeden Fall etwas falsch mit dem Mono-Compiler zu sein, der referenzierte System-Assemblies abruft. Wenn ich direkt auf die Probe ihres csharp Konsolen-Tool kopieren:
csharp> var list = new int [] {1,2,3};
csharp> var b = from x in list
> where x > 1
> select x;
csharp> b;
ich die Ausnahme erhalten:
{interactive}(1,25): error CS1935: An implementation of `Select' query expressio
n pattern could not be found. Are you missing `System.Linq' using directive or `
System.Core.dll' assembly reference?
auch in Ordnung, für den MCS, um tatsächlich eine realisierbare Lösung zu sein, ich werde müssen Ändern Sie den Compiler so, dass er an eine einzige dynamische Assembly gesendet wird, anstatt eine Assembly pro Evaluierungsaufruf auszugeben (andernfalls wird ein größerer Speicherverlust angezeigt, den ich zuvor in Form des CSharpCodeProviders behandelt habe). Hat jemand eine Vorstellung davon, wie schwer das sein wird oder kann mir hier jemand in die richtige Richtung zeigen?
Danke.
warum nicht http://msdn.microsoft.com/en-us/library/microsoft.csharp.csharpcodeprovider(VS.80).aspx zu benutzen? – Andrey
CSharpCodeProvider sendet und lädt eine Assembly pro Kompilierung (auch wenn Sie die Option Nur im Arbeitsspeicher verwenden). Ich werde Tausende von Auswertungen durchführen und somit Tausende von Assemblys in die ausführende AppDomain laden (Speicherleck). Außerdem verwendet CSharpCodeProvider intern csc.exe, das weitaus rechenintensiver als Reflection.Emit ist. In einem früheren Projekt habe ich CSharpCodeProvider verwendet und Evaluierungen in einer separaten Anwendungsdomäne ausgeführt, die basierend auf der Assembly-Anzahl wiederverwendet wurde. Dies erwies sich jedoch als enormer Wartungsaufwand und sehr fehleranfällig. Daher möchte ich diesen Ansatz vermeiden. – Jeff
Auch, ich weiß, dass standardmäßig MCS auch eine einzelne Assembly pro evaluieren, aber da es auf Reflection.Emit intern beruht, hoffe ich, dass ich dieses Verhalten auf eine einzelne Assembly emittieren können, wie von AppDomain.DefineDynamicAssembly definiert. – Jeff