一、基本概念:
--托管模块:一个标准的32的可移植执行体(PE32)文件或一个标准的64位可移植执行体(PE32+)文件。由用支持CLR的任何一种语言创建的源代码文件,再经过相应的编译器检查语法和分析源代码,编译生成。如下:
--程序集:由一或者多个模块/资源文件的逻辑性组合。程序集是重用、安全性以及版本控制的最小单元。
可以将.exe与.dll文件认为是一个程序集;其中.exe文件是一个自己执行的程序集,而.dll将被其他程序集加载后运行。
二、模块与程序集概念的类比
一个项目的开发团队,会有一个或者是多个的“成员”组成,这些“成员”里必定会有一个负责人。团队外部的人要和这个团队打交道,他们只需要知道这个团队的负责人即可。因为这个负责人“成员”知道这个团队内部的一切情况。在很多情况下,团队外部的人员会以负责人的名称来称呼这一个团队。在这里,团队是一个逻辑的概念,并不是特指某个人或资源。
团队 = 程序集
负责人 = 主模块(下面会说明与普通模块的区别)
成员 = 普通模块
在很多情况下,我们会用主模块的特征(如名称)来称呼一个程序集。即(用负责人“成员”的特征来称呼一个团队)
三、模块与程序集的生成
1、cs文件
假设我有两个.cs的类库文件,和一个包含Main方法的.cs文件,都放在D:\test文件夹中。分别为:
Cat.cs:
using System;
namespace Animal
{
public class Cat
{
public void Print()
{
Console.WriteLine("cat");
}
}
}
Dog.cs:
using System;
namespace Animal
{
public class Dog
{
public void Print()
{
Console.WriteLine("dog");
}
}
}
Program.cs
using Animal;
public class Program
{
static void Main(string[] args)
{
new Dog().Print();
new Cat().Print();
}
}
2、生成类库程序集
现在可以将这两个.cs文件生成相应的模块,利用csc.exe编译器:
csc /t:module /out:D:\test\Cat.netmodule D:\test\Cat.cs
csc /t:module /out:D:\test\Dog.netmodule D:\test\Dog.cs
这个会在D:\test目录下生成两个普通模块:
Cat.netmodule
Dog.netmodule
由于CLR是以程序集作为最小单元进行加载的,为了使Program.cs文件能够正常地调用Cat.netmodule与Dog.netmodule/现将这两个文件生成一个程序集。由于这个程序集是一个被其他程序集加载的,因此,生成的文件名可以为:Animal.dll
csc /out:D:\test\Animal.dll /t:library /addmodule:D:\test\Cat.netmodule;D:\test\Dog.netmodule
执行此命令之后,会在D:\test目录下生成Animal.dll
上面的各个模块中:
主模块(负责人):Animal.dll
普通模块(成员): Cat.netmodule, Dog.netmodule。
程序集(团队):由主模块Animal.dll与普通模块Cat.netmodule、Dog.netmodule组成。但是在一般情况下我们会将Animal.dll称为程序集。特别是在IDE 的visual studio的生成的情况下,因为在IDE默认生成的dll中,已经将各个模块包含进dll中,除了dll中,并没有其他的模块文件。
在这里,我们可以运行命令:
csc /out:D:\test\Animal.dll /t:library D:\test\Cat.cs D:\test\Dog.cs直接生成Animal.dll文件,此时将不再生成Cat.netmodule与Dog.netmodule文件;
3、exe调用dll
执行命名:
csc /out:D:\test\Program.exe /R:D:\test\Animal.dll D:\test\Program.cs
将会在D:\test生成Program.exe可运行文件
注意:这里的Animal.dll文件代表的是一个程序集,如果这个程序集由多个文件组成,必须保证其他文件都存在,否则编译会失败。如当程序集由主模块Animal.dll、普通模块Cat.netmodule与Dog.netmoudle组成时,必须保证这三个文件同时存在。
在命令行中可以直接执行: Program.exe
输入结果:
dog
cat
4、一个程序集多个模块的作用
CLR是以程序集为单位进行加载的。但是,CLR只会加载被引用到的模块,没有引用的模块不会加载。因此,可以将程序集分为多个模块,运行程序时,只要保证有被引用到的模块存在即可,可以减少加载的程序集文件大小;特别是当程序集是通过网络传输加载时。
示例:
修改Program.cs文件,使它不再引用Cat.cs文件中的类型
using Animal;
public class Program
{
static void Main(string[] args)
{
new Dog().Print();
// new Cat().Print();
}
}
重新编译Program.cs文件:
csc /out:D:\test\Program.exe /R:D:\test\Animal.dll D:\test\Program.cs
现在在D:\test文件夹中具有文件如下:
运行Program.exe,结果:
现在将Cat.netmodule删除:
运行Program.exe,结果:
原因是:CLR并没有加载Cat.netmodule,因此,就算这个普通模块不存在也无所谓。