2010-05-13 15 views
16

Estoy tratando de averiguar si es posible cuando se generan ensamblajes dinámicamente, para hacer referencia a un tipo en un ensamblaje generado dinámicamente previamente.C# - Hacer referencia a un tipo en un ensamblaje generado de forma dinámica

Por ejemplo:

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

CodeDomProvider provider = new CSharpCodeProvider(); 
CompilerParameters parameters = new CompilerParameters(); 

parameters.GenerateInMemory = true; 

CompilerResults results = provider.CompileAssemblyFromSource(parameters, @" 
namespace Dynamic 
{ 
    public class A 
    { 
    } 
} 
"); 

Assembly assem = results.CompiledAssembly; 

CodeDomProvider provider2 = new CSharpCodeProvider(); 
CompilerParameters parameters2 = new CompilerParameters(); 

parameters2.ReferencedAssemblies.Add(assem.FullName); 
parameters2.GenerateInMemory = true; 

CompilerResults results2 = provider2.CompileAssemblyFromSource(parameters2, @" 
namespace Dynamic 
{ 
    public class B : A 
    { 
    } 
} 
"); 

if (results2.Errors.HasErrors) 
{ 
    foreach (CompilerError error in results2.Errors) 
    { 
     Console.WriteLine(error.ErrorText); 
    } 
} 
else 
{ 
    Assembly assem2 = results2.CompiledAssembly; 
} 

Este código imprime lo siguiente en la consola: The type or namespace name 'A' could not be found (are you missing a using directive or an assembly reference?)

Lo he intentado un montón de diferentes maneras, pero nada parece estar funcionando. ¿Me estoy perdiendo de algo? ¿Esto es posible?

EDIT: La fijación del error en el código ofrece este error en su lugar: Metadata file 'l0livsmn, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' could not be found

Edit2: Un poco de una nota al margen, pero cambiando GenerateInMemory a falso, y haciendo parameters2.ReferencedAssemblies.Add(assem.Location); hará que se compila correctamente, pero yo' Preferiría mucho hacer referencia al ensamblaje que está directamente en la memoria en lugar de enviar archivos temporales.

Respuesta

4

Creo que en

CompilerResults results2 = provider2.CompileAssemblyFromSource(parameters, @" 
namespace Dynamic 
{ 
    public class B : A 
    { 
    } 
} 
"); 

Se debe pasar parameters2, no parameters.

Encontré la forma de hacerlo, no necesita compilar el primero en la memoria, si no lo hace, creará un dll para este ensamblado en su directorio temporal, además, en su llamada a

ReferencedAssemblies.Add() 

usted no pase el nombre de ensamblado, se pasa la ruta de montaje, echar un vistazo a este código, que debería funcionar sin problemas:

 CodeDomProvider provider = new CSharpCodeProvider(); 
     CompilerParameters parameters = new CompilerParameters();    

     CompilerResults results = provider.CompileAssemblyFromSource(parameters, @" 
      namespace Dynamic 
      { 
       public class A 
       { 
       } 
      } 
      "); 

     Assembly assem = results.CompiledAssembly; 

     CodeDomProvider provider2 = new CSharpCodeProvider(); 
     CompilerParameters parameters2 = new CompilerParameters(); 

     parameters2.ReferencedAssemblies.Add(assem.Location); 
     parameters2.GenerateInMemory = true; 

     CompilerResults results2 = provider2.CompileAssemblyFromSource(parameters2, @" 
      namespace Dynamic 
      { 
       public class B : A 
       { 
       } 
      } 
      "); 

     if (results2.Errors.HasErrors) 
     { 
      foreach (CompilerError error in results2.Errors) 
      { 
       Console.WriteLine(error.ErrorText); 
      } 
     } 
     else 
     { 
      Assembly assem2 = results2.CompiledAssembly; 
     } 
+0

Ah, disparar. ¡Gracias! Lo arreglé. Ver la edición. – Ashley

+0

Ver mi segunda edición. Creo que lo descubrimos casi al mismo tiempo. Todavía me gustaría poder hacer referencia al ensamblaje en memoria, si es posible. – Ashley

+0

Parece que el código fuente se ejecuta y creó el segundo conjunto. Pero si intenta cargar los tipos residen en el segundo ensamblado (usando assem2.GetTypes()), obtendrá una ReflectionTypeLoadException –

2

MSDN dice que se puede:

restricciones en el tipo Referencias

ensamblajes pueden hacer referencia a tipos definidos en otro conjunto. A ensamblado dinámico transitorio puede hacer referencia de forma segura tipos definidos en otro conjunto dinámico transitorio , un ensamblado dinámico con persistencia, o un conjunto estático . Sin embargo, el tiempo de ejecución de lenguaje común no permite un módulo dinámico persistente a referencia un tipo definido en un módulo dinámico transitorio . Esto es porque cuando se carga el módulo dinámico persistente después de guardarse en el disco , el tiempo de ejecución no puede resolver las referencias a los tipos definidos en el módulo dinámico transitorio .

+2

Bueno, supongo que la pregunta ahora es: "¿Cómo hago referencia al ensamblaje dinámico transitorio en la memoria?" – Ashley

+0

Me pregunto: el ensamblado se crea en la memoria, pero ¿está agregado a ApplicationDomain de forma predeterminada? ¿O lo cargarías tú mismo? O llama a 'AppDomain.DefineDynamicAssembly'? –

+0

Hmm, esa es una buena pregunta. Intenté jugar un poco, y el ensamble generado dinámicamente definitivamente parece estar cargado. – Ashley

Cuestiones relacionadas