2010-08-04 6 views
8

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.

+0

por qué no usar http://msdn.microsoft.com/en-us/library/microsoft.csharp.csharpcodeprovider(VS.80).aspx? – Andrey

+1

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

+0

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

Respuesta

2

Ok, creo que tengo algunas respuestas.

Para resolver el problema de carga de montaje, ya sea que puedo realizar una llamada a Assembly.LoadWithPartialName dentro Mono.CSharp.Driver.LoadAssembly, o hacer lo siguiente en mi solicitud

 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 hacer Mono reutilizar el mismo Ensamblaje dinámico para cada llamada de Evaluar/Compilar, todo lo que tuve que cambiar fue lo siguiente (aunque probablemente haya complejidades que me faltan aquí) .....

Dentro de Mono.CSharp.Evaluador, añadí la propiedad:

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

Entonces ... asegurarse de reinicio se llama al menos una vez en Init:

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

Y, por último, en parseString, simplemente no pone a cero a menos AutoReset es cierto ...

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

Entonces, estoy teniendo el mismo problema. ¿Hay una versión compilada de Mono.CSharp.dll que tenga los cambios que describes arriba? Me gustaría usar esto en una aplicación, pero me parece muy inestable. –

+0

¿Qué problema tienes? ¿Has intentado hacer los cambios que mencioné arriba? Si realmente lo necesita, puedo proporcionar un dll, pero probablemente sea mejor que solo realice estos cambios y compile el dll usted mismo. – Jeff

+0

Además, por mi parte, después de hacer estos cambios no he encontrado ningún otro problema ... ¿o sí? – Jeff

1

Según la página de blog de Miguel que ha vinculado, debe agregar una referencia a System.Core para poder usar LINQ en .Net.

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

Ah ... Ya veo, pero agregar una referencia no es suficiente porque no copia los ensamblajes de GAC o ensamblajes de armazones en el directorio bin. – Jeff

Cuestiones relacionadas