2008-10-11 84 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;");