【问题标题】:.NET Module vs Assembly.NET 模块与程序集
【发布时间】:2012-02-14 04:41:42
【问题描述】:

我一直在努力思考这个“正确”的答案? stackoverflow 上有几个主题涵盖了这一点,但这与 msdn 文档有些冲突。

例如,请注意他的问题的第二个答案中的图表:What is a Managed Module (compared to an Assembly)?

现在看msdn图:http://msdn.microsoft.com/en-us/library/zst29sk2(VS.100).aspx

msdn 图暗示单文件程序集不包含模块,而是由清单、il 代码、类型元数据等组成。 这与我读过的许多其他文章不同,后者指出单个文件程序集有一个模块。

答案是什么?如果答案是“两者”,那么模块是否是通过程序集清单链接的单独物理文件?

【问题讨论】:

标签: c# .net


【解决方案1】:

在 .net 中,程序集和模块之间的区别在于模块 不包含清单

//Copied from CLR via C#

什么是清单?

清单是另一组 元数据表基本上包含作为程序集一部分的文件的名称。他们也 描述程序集的版本、文化、发布者、公开导出的类型以及所有文件 组成大会。

CLR 对程序集进行操作;也就是说,CLR 总是加载包含清单的文件 首先元数据表,然后使用清单来获取程序集中的其他文件/模块的名称。

如何将模块组合成一个程序集?

使用 C# 编译器

了解如何构建多文件/多模块 汇编,假设我们有两个源代码文件:

■■ RUT.cs,其中包含很少使用的类型

■■ FUT.cs,包含常用类型

让我们将很少使用的类型编译到他们自己的模块中,这样程序集的用户就不需要 如果他们从不访问很少使用的类型,则部署此模块。

csc /t:module RUT.cs

这一行使 C# 编译器创建一个 RUT.netmodule 文件。这个文件是一个标准的 DLL PE 文件, 但是,CLR 本身无法加载它。 接下来让我们将常用的类型编译到他们自己的模块中。我们将使这个模块成为 程序集清单的管理员,因为这些类型经常使用。事实上,因为这个模块 现在将代表整个程序集,我将输出文件的名称更改为 MultiFileLibrary.dll 而不是调用它 FUT.dll。

csc /out:MultiFileLibrary.dll /t:library /addmodule:RUT.netmodule FUT.cs

这一行告诉 C# 编译器编译 FUT.cs 文件以生成 MultiFileLibrary.dll 文件。因为 /t:library 被指定,包含清单元数据表的 DLL PE 文件被发送到 MultiFileLibrary.dll 文件。 /addmodule:RUT.netmodule 开关告诉编译器 RUT.netmodule 是一个应该被视为程序集一部分的文件。具体来说,/addmodule 开关告诉 编译器将文件添加到 FileDef 清单元数据表并公开添加 RUT.netmodule 将类型导出到 ExportedTypesDef 清单元数据表。

编译器完成所有处理后,将创建图 2-1 所示的两个文件。 右侧的模块包含清单。

使用汇编链接器

AL.exe 实用程序可以生成 EXE 或 DLL PE 文件,其中仅包含描述 其他模块中的类型。要了解 AL.exe 的工作原理,让我们更改 MultiFileLibrary.dll 的方式 程序集已构建。

csc /t:module RUT.cs
csc /t:module FUT.cs
al /out: MultiFileLibrary.dll /t:library FUT.netmodule RUT.netmodule

图 2-3 显示了执行这些语句产生的文件。

我建议您阅读 CHAPTER 2: Building, Packaging, Deploying, and Administering Applications and Types from CLR via C# by Jeffrey Richter,以详细了解这个概念.

【讨论】:

    【解决方案2】:

    每个程序集至少有一个模块。这是一个高度不可见的实现细节。但是当你使用 Reflection.Emit 时你可以看到它。来自AssemblyBuilder class的示例代码:

    AssemblyName aName = new AssemblyName("DynamicAssemblyExample");
    AssemblyBuilder ab = 
        AppDomain.CurrentDomain.DefineDynamicAssembly(
            aName, 
            AssemblyBuilderAccess.RunAndSave);
    
    // For a single-module assembly, the module name is usually
    // the assembly name plus an extension.
    ModuleBuilder mb = 
        ab.DefineDynamicModule(aName.Name, aName.Name + ".dll");
    
    TypeBuilder tb = mb.DefineType(
        "MyDynamicType", 
         TypeAttributes.Public);
    

    注意 ModuleBuilder 类的使用,将类型添加到模块中。一个程序集可以包含多个模块是无关紧要的,构建环境不支持它。不只是 IDE,MSBuild 也不支持它。您必须自己编写构建脚本才能使用al.exe, the assembly linker。我认为没有充分的理由这样做,所有 .NET 编译器都已经知道如何直接生成单个模块程序集。 Al.exe 是一个典型的引导工具,可能用于构建 mscorlib.dll。

    【讨论】:

    • 我一直想知道循环依赖有一段时间,但不敢问。我不知道 为什么 mscorlib 和 system 具有循环依赖关系,但您能否简要解释一下我如何维护两个相互引用的项目(在同一个解决方案中或不在同一个解决方案中)?
    • @RaheelKhan 的答案是“你不知道”,将常见的部分重构为两个程序集都可以引用的第三个程序集。一个非常常见的现实世界示例是插件架构,您的程序集和其他程序集都引用了定义所有接口的第三个 API 程序集。然后,您可以使用反射来创建插件的实例并将其投射到您的程序和插件共享的公共接口。
    【解决方案3】:

    模块是程序集中代码的逻辑集合。一个程序集中可以有多个模块,每个模块可以用不同的 .NET 语言编写(据我所知,VS 不支持创建多模块程序集)。

    程序集包含模块。模块包含类。类包含函数。

    发件人:What is a module in .NET?

    真正来自:必应搜索“.NET 模块与程序集”

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-11-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-13
      相关资源
      最近更新 更多