2008-10-11 174 views
3

我有一些非常簡單的代碼來生成一個程序集並調用一個包含類型的方法。該方法被調用並正確運行,但是當我使用Reflector查看生成的程序集時,我看不到該類型。大會不正確保存

下面是示例代碼:

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

,這裏是從反射相應的拆卸:

.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 

......還有......

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

誰能幫助我是否正確地保存了程序集?

回答

4

訣竅是用DefineDynamicModule方法的「持久化的模塊」的版本上AssemblyBuilder實例。也就是說,不是,:

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

使用類似:

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

此後,相應的模塊將出現在裝配保存後。

-1

我不確定爲什麼類型沒有被添加。

但是,這樣做的另一種方法是通過傳入包含類代碼的字符串來動態創建代碼。我認爲這比上面的方式更簡單一些,因爲您可以使用字符串構建器在studio中構建代碼並進行測試。

這裏是我使用,以產生一個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;");