.NET模块与汇编

mik*_*010 54 .net c#

我一直试图围绕这个'正确'的答案?stackoverflow上有几个主题涵盖了这一点,但与msdn文档有些冲突.

例如,请注意他的问题的第二个答案中的图表:什么是托管模块(与组件相比)?

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

msdn图表意味着单个文件程序集不包含模块,而是包含清单,il代码,类型元数据等.这与我读过的许多其他文章不同,后者指出单个文件程序集具有一个模块.

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

Dee*_*hra 62

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

//Copied from CLR via C#
Run Code Online (Sandbox Code Playgroud)

什么是明显的?

清单是另一组元数据表,它基本上包含作为程序集一部分的文件的名称.它们还描述了程序集的版本,区域性,发布者,公开导出的类型以及组成程序集的所有文件.

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

如何将模块组合成一个组件?

使用C#编译器

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

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

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

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

csc /t:module RUT.cs
Run Code Online (Sandbox Code Playgroud)

此行导致C#编译器创建RUT.netmodule文件.此文件是标准DLL PE文件,但是,CLR本身无法加载它.接下来让我们将常用类型编译到自己的模块中.我们将使这个模块成为程序集清单的守护者,因为这些类型经常被使用.实际上,因为此模块现在将代表整个程序集,所以我将输出文件的名称更改为MultiFileLibrary.dll,而不是将其命名为FUT.dll.

csc /out:MultiFileLibrary.dll /t:library /addmodule:RUT.netmodule FUT.cs
Run Code Online (Sandbox Code Playgroud)

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

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

在此输入图像描述

使用Assembly Linker

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
Run Code Online (Sandbox Code Playgroud)

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

在此输入图像描述

我建议你读第2章:建筑,包装,部署和管理应用程序和类型由杰弗里里希特通过C#CLR来详细了解这个概念.

  • downvoters应该写出他们的理由. (4认同)

Han*_*ant 38

每个组件至少有一个模块.这是一个高度不可见的实现细节.但是当你使用Reflection.Emit时你可以看到它.从AssemblyBuilder类的示例代码:

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);
Run Code Online (Sandbox Code Playgroud)

注意使用ModuleBuilder类,将类型添加到模块中.程序集可以包含多个模块是非常不相关的,构建环境不支持它.不仅仅是IDE,MSBuild也不支持它.您必须自己编写构建脚本才能使用al.exe(程序集链接器).我无法理解这一点,所有.NET编译器都已经知道如何直接生成单个模块组件.Al.exe是一种典型的引导工具,可能用于构建mscorlib.dll.

  • @RaheelKhan的答案是“您不要”,将常见零件重构为两个程序集都可以引用的第三个程序集。现实世界中一个非常常见的示例是插件体系结构,您的程序集和另一个程序集均引用定义了所有接口的第3个API程序集。然后,您可以使用反射来创建插件的实例,并将其强制转换为程序和插件共享的通用接口。 (3认同)
  • 我一直想知道循环依赖已经有一段时间但是却不敢问.我不知道**为什么**mscorlib和系统有循环依赖关系,但是你能非常简单地解释一下我如何维护两个相互引用的项目(在相同的解决方案中)? (2认同)

GGu*_*ati 16

模块是程序集中代码的逻辑集合.您可以在程序集中包含多个模块,并且每个模块都可以使用不同的.NET语言编写(据我所知,VS不支持创建多模块程序集).

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

来自:.NET中的模块是什么?

真的来自:Bing搜索".NET模块与汇编"