Mono Compiler as a Service (MCS)

Me gustaría consumir el comstackdor de Mono como un servicio de mi aplicación regular .NET 3.5.

He descargado los últimos bits (2.6.7), he creado una aplicación de consola simple en Visual Studio y he hecho referencia al dll Mono.CSharp.

Luego, en mi aplicación de consola (directamente de una muestra en línea):

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(' '); } 

Esto arroja una excepción en Evaluator.Run (la primera línea):

 Illegal enum value: 2049. Parameter name: access 

Esto se debe a que el dll se compiló usando Mono.exe, no csc.exe, creo.

Intenté descargar el dll Mono.CSharp directamente desde http://tirania.org/blog/archive/2010/Apr-27.html en el archivo demo-repl.zip … y eso no arroja una excepción. .. Sin embargo, el parámetro de salida (res) después de llamar a Evaluator.Evaluate es nulo … así que no estoy seguro de lo que está pasando mal. No se arroja ninguna excepción …

Entonces, me gustaría descubrir por qué el dll que descargué de demo-repl.zip devuelve null.

EDIT: descubrí por qué devuelve null. Parece que por alguna razón el comstackdor no está recogiendo el espacio de nombres System.Linq … aunque no puedo decir por qué … Si simplemente evalúo “System.IO.Directory.GetFiles (\” C: \\ “)”, funciona bien.

ACTUALIZACIÓN: Definitivamente parece que hay algo mal con el comstackdor Mono recogiendo ensambles de sistema referenciados. Si copio directamente la muestra de su herramienta de consola csharp:

 csharp> var list = new int [] {1,2,3}; csharp> var b = from x in list > where x > 1 > select x; csharp> b; 

Obtengo la excepción:

 {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? 

Además, para que el MCS sea realmente una solución factible, tendré que modificar el comstackdor para que emita un solo ensamblaje dynamic, en lugar de emitir un ensamblado por llamada de evaluación (de lo contrario, presenta una fuga de memoria importante, que He tratado antes en la forma de CSharpCodeProvider). ¿Alguien tiene una idea de lo difícil que será o puede alguien señalarme en la dirección correcta aquí?

Gracias.

Ok, creo que tengo algunas respuestas.

Para resolver el problema de carga del ensamblaje, puedo realizar una llamada a Assembly.LoadWithPartialName dentro de Mono.CSharp.Driver.LoadAssembly, o hacer lo siguiente en mi aplicación

  AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve); private static bool isResolving; static System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) { if (!isResolving) { isResolving = true; var a = Assembly.LoadWithPartialName(args.Name); isResolving = false; return a; } return null; } 

Para que Mono reutilice el mismo conjunto dynamic para cada llamada de Evaluar / Comstackr, todo lo que tuve que cambiar fue lo siguiente (aunque probablemente haya complejidades que me faltan aquí) …..

Dentro de Mono.CSharp.Evaluator, agregué la propiedad:

 ///  /// Gets or sets a value indicating whether to auto reset when evaluations are performed and create a new assembly. ///  /// true if [auto reset]; otherwise, false. public static bool AutoReset { get; set; } 

Entonces … asegúrate de que se llama Reset al menos una vez en Init:

  static void Init () { Init (new string [0]); Reset(); } 

Y finalmente, en ParseString, simplemente no restablecer a menos que AutoReset sea verdadero …

  static CSharpParser ParseString (ParseMode mode, string input, out bool partial_input) { . . . if (AutoReset) Reset (); 

De acuerdo con la página de blog de Miguel que vinculó, debe agregar una referencia a System.Core para poder usar LINQ en .Net.

 csharp> using System.Linq; csharp> from x in "Foo" select x;