2008-10-11 3 views
3

J'ai un code très simple pour générer un assembly et appeler une méthode sur un type contenu. La méthode est appelée et s'exécute correctement, cependant lorsque je vois l'assembly généré en utilisant Reflector, je ne vois pas le type.L'assemblage n'est pas enregistré correctement

Ci-dessous le code exemple:

namespace ConsoleApplication2 
{ 
    class Proggy 
    { 
     public static void Main(string[] args) 
     { 
      var ab = AppDomain.CurrentDomain.DefineDynamicAssembly(
       new AssemblyName() { Name = "MyAssembly" }, 
       AssemblyBuilderAccess.RunAndSave); 
      var module = ab.DefineDynamicModule(ab.GetName().Name); 
      var typeBuilder = module.DefineType("MyType"); 
      var ctr = typeBuilder.DefineConstructor(MethodAttributes.Public, 
       CallingConventions.Standard, Type.EmptyTypes); 
      var ilgc = ctr.GetILGenerator(); 
      ilgc.Emit(OpCodes.Ldarg_0); 
      ilgc.Emit(OpCodes.Call, typeof(object).GetConstructor(Type.EmptyTypes)); 
      ilgc.Emit(OpCodes.Ret); 
      var method = typeBuilder.DefineMethod("MyMethod", MethodAttributes.Public, 
       typeof(int), new[] { typeof(string) }); 
      var ilg = method.GetILGenerator(); 
      ilg.Emit(OpCodes.Ldarg_1); 
      ilg.EmitCall(OpCodes.Callvirt, typeof(string).GetProperty("Length").GetGetMethod(), 
       null); 
      ilg.Emit(OpCodes.Ret); 
      var type = typeBuilder.CreateType(); 
      ab.Save("mytestasm.dll"); 
      var inst = Activator.CreateInstance(type); 
      Console.WriteLine(type.InvokeMember("MyMethod", BindingFlags.InvokeMethod, null, inst, 
       new[] { "MyTestString" })); 
      Console.ReadLine(); 
     } 
    } 
} 

et est ici le démontage correspondant du réflecteur:

.assembly MyAssembly 
{ 
    .ver 0:0:0:0 
    .hash algorithm 0x00008004 
} 
.module RefEmit_OnDiskManifestModule 
// MVID: {0B944140-58D9-430E-A867-DE0AD0A8701F} 
// Target Runtime Version: v2.0.50727 

... et ...

{ 
    .class private auto ansi <Module> 
    { 
    } 
} 

peut-elle aider quelqu'un moi avec obtenir l'assemblage correctement enregistré?

Répondre

4

L'astuce est d'utiliser une version "module persistable" de la méthode DefineDynamicModule sur l'instance AssemblyBuilder. Autrement dit, au lieu de:

var module = ab.DefineDynamicModule(ab.GetName().Name); 

utiliser quelque chose comme:

var module = ab.DefineDynamicModule(ab.GetName().Name, ab.GetName().Name + ".mod"); 

Ensuite, le module correspondant apparaît dans l'assemblage après l'enregistrement.

-1

Je ne sais pas pourquoi le type n'est pas ajouté.

Une autre façon de procéder est de créer du code de façon dynamique en passant simplement une chaîne contenant votre code de classe. Je pense que c'est un peu plus facile que la méthode ci-dessus, car vous pouvez simplement construire le code en utilisant un constructeur de cordes et tester en studio.

Voici le code que je l'utilise pour générer une dll:

print(" Microsoft.CSharp.CSharpCodeProvider objCodeProvider = new Microsoft.CSharp.CSharpCodeProvider(); 
     string strCode = "using System;" + Environment.NewLine + "using System.Data;" + Environment.NewLine + "using DC.Common;" + Environment.NewLine + "" + Environment.NewLine + "using System.Data.SqlClient;" + Environment.NewLine + "using System.Configuration;" + Environment.NewLine + "" + Environment.NewLine + Environment.NewLine + BaseClassFile + Environment.NewLine + BaseManagerFile + Environment.NewLine; 
     string strSourceModule = BuilderSettings.ExportDir + "/" + BuilderSettings.ProjectName + "/" + "BaseFile.cs"; 

     FileHelper.WriteAllText(strSourceModule, strCode); 
     FileHelper.WriteAllText(BuilderSettings.ExportDir + "/" + BuilderSettings.ProjectName + "/" + "test.txt", strCode); 

     ICodeCompiler icc = objCodeProvider.CreateCompiler(); 
     string OutputPath = BuilderSettings.ExportDir + "/" + BuilderSettings.ProjectName + "/" + BuilderSettings.ProjectName + ".dll"; 
     CompilerParameters parameters = new CompilerParameters(); 
     CompilerResults results; 

     parameters.GenerateExecutable = false; 
     parameters.OutputAssembly = OutputPath; 
     parameters.GenerateInMemory = false; 
     parameters.IncludeDebugInformation = false; 

     //Add required assemblies 
     DynamicLinkLibraries.Clear(); 

     //User defined 
     DynamicLinkLibraries.Add(@"d:\wwwroot\\DC.Common\bin\Debug\DC.Common.dll"); 

     //System 
     DynamicLinkLibraries.Add("System.dll"); 
     DynamicLinkLibraries.Add("System.Data.dll"); 
     DynamicLinkLibraries.Add("mscorlib.dll"); 
     DynamicLinkLibraries.Add("System.xml.dll"); 
     DynamicLinkLibraries.Add("System.web.dll"); 
     DynamicLinkLibraries.Add("System.configuration.dll"); 

     //Any dynamic assembly adding must be done here 
     foreach (string strLibrary in DynamicLinkLibraries) 
     { 
      parameters.ReferencedAssemblies.Add(strLibrary); 
     } 

      results = icc.CompileAssemblyFromSource(parameters, strCode); 

      if (results.Errors.Count > 0) 
      { 
       //report any compilation errors 
       string strErrors = "Compilation failed:" + Environment.NewLine; 

       foreach (CompilerError oError in results.Errors) 
       { 
        strErrors = strErrors + "Line number " + oError.Line + ", Error Number: " + oError.ErrorNumber + ", '" + oError.ErrorText + ";"; 

       } 

       throw new Exception("Error in CompileSourceCode(): " + Environment.NewLine + strErrors); 
      } 

      objCodeProvider = null; 
      icc = null; 
      parameters = null;"); 
Questions connexes