Me gustaría consumir el compilador de Mono como un servicio de mi aplicación regular .NET 3.5.Monocompilador como un servicio (MCS)
He descargado los últimos bits (2.6.7), he creado una aplicación de consola simple en Visual Studio y he mencionado el dll Mono.CSharp.
Entonces, 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(' ');
}
Esta lanza una excepción en Evaluator.Run (la primera línea):
Illegal enum value: 2049.
Parameter name: access
Esto se debe a el dll fue compilado usando Mono.exe, no csc.exe, creo.
He intentado 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 out (res) después de llamar a Evaluator.Evaluate es nulo ... así que no estoy seguro de lo que está pasando mal. No se lanza 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 compilador 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 compilador Mono que recoge los ensamblajes del sistema mencionados. 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;
consigo 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 para ser realmente una solución viable, que necesitaré modifique el compilador para que emita un solo ensamblaje dinámico, en lugar de emitir un ensamblado por llamada de evaluación (de lo contrario, presenta una fuga de memoria importante, que he tratado anteriormente 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.
por qué no usar http://msdn.microsoft.com/en-us/library/microsoft.csharp.csharpcodeprovider(VS.80).aspx? – Andrey
CSharpCodeProvider emite y carga un ensamblado por compilación (incluso si usa la opción solo en memoria). Realizaré miles de evaluaciones y, por lo tanto, tendré miles de ensamblajes cargados en el AppDomain de ejecución (pérdida de memoria). Además, CSharpCodeProvider usa internamente csc.exe, que es mucho más intensivo que Reflection.Emit. En un proyecto anterior, utilicé CSharpCodeProvider y realicé evaluaciones en un dominio de aplicación separado que se recicló en función del recuento de ensamblados, pero esto demostró ser una enorme sobrecarga de mantenimiento y propensa a errores, por lo que me gustaría evitar ese enfoque. – Jeff
Además, me doy cuenta de que, de forma predeterminada, MCS también hace un único ensamblado por evaluación, pero dado que depende de Reflection.Emit internamente, espero poder cambiar ese comportamiento para emitir a un solo ensamblaje como lo define AppDomain.DefineDynamicAssembly. – Jeff