程序集未正确保存

发布于 2024-07-06 17:09:21 字数 1998 浏览 7 评论 0原文

我有一些非常简单的代码来生成程序集并调用包含的类型上的方法。 该方法被调用并正确运行,但是当我使用 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();
        }
    }
}

这是 Reflector 的相应反汇编:

.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>
    {
    }
}

任何人都可以帮助我正确保存程序集吗?

I have some very simple code to generate an assembly and invoke a method on a contained type. The method gets called and runs correctly, however when I view the generated assembly using Reflector, I don't see the type.

Below is the sample code:

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

and here is the corresponding disassembly from Reflector:

.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

... and ...

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

Can anyone help me with getting the assembly properly saved?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

错々过的事 2024-07-13 17:09:21

诀窍是在 AssemblyBuilder 实例上使用 DefineDynamicModule 方法的“持久模块”版本。 也就是说,不要使用:

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

使用类似以下内容的内容:

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

此后,保存后相应的模块会出现在程序集中。

The trick is to use a "persistable module" version of DefineDynamicModule method on the AssemblyBuilder instance. That is, instead of:

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

use something like:

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

Thereafter the corresponding module appears in the assembly after saving.

深海夜未眠 2024-07-13 17:09:21

我不确定为什么没有添加该类型。

然而,执行此操作的另一种方法是通过仅传入包含类代码的字符串来动态创建代码。 我认为这比上面的方法更容易,因为您可以使用字符串生成器构建代码并在工作室中进行测试。

这是我用来生成 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;");

I am not sure why the type is not getting added.

Another way of doing this however is to dynamically create code by just passing in a string which contains your class code. I think this is a bit easier than the above way of doing it as you can just build up the code using a string builder and test in studio.

Here is the code i use to generate a 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;");
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文