Assembly是.net中的基本部署单元,也是所有类型的容器。程序集包含编译类型及其 IL(中间语言)代码、运行时资源和信息,以助于版本控制、安全和引用其他程序集。程序集定义了类型解析和安全许可的边界。
一般来说,一个程序集包括一个单一的Windows可移植执行文件(PE)--如果是一个应用程序,扩展名为.exe,如果是一个可重用的库,扩展名为.dll。WinRT库的扩展名是.winmd,与.dll类似,只是它只包含元数据,没有IL代码。
本节的大多数类型来自下面几个命名空间:
System.Reflection
System.Resources
System.Globalization
Assembly具体是什么
一个Assembly包含四类文件(数据):
- 程序集清单(assembly manifest):
向.net运行时提供的信息,比如程序集的名称,版本,要求的许可,以及它引用的其他程序集。
- 应用程序清单(An application manifest):
向操作系统提供的信息,比如程序集应该如何被部署,是否需要管理员权限。
- 已编译的类型(Compiled types):
已编译的 IL 代码和程序集中定义的类型的元数据
- 资源(Resources)
程序集重点其他数据,比如图片和本地文本。
只有程序集清单(assembly manifest)是必须的,尽管一个程序集几乎总是包含编译过的类型(除非它是一个WinRT参考程序集)。
无论是可执行文件还是库,程序集的结构都是相似的。这与可执行文件的主要区别在于它定义了一个入口点。
程序集清单(The Assembly Manifest)
程序集清单有两个目的:
- 向托管主机环境描述程序集
- 它充当程序集中模块(modules)、类型(types)和资源(resources)的目录
因此,程序集是自描述的。使用者以发现一个程序集的所有数据、类型和函数,而不需要额外的文件。
程序集清单不需要你手动添加到程序集,它作为编译的一部分自动嵌入到程序集中的
清单内容
以下是清单中存储的具有重要功能的数据的:
- 程序集的简单名称
- 一个版本号(AssemblyVersion)
- 程序集的公钥和签名哈希(如果有强命名)
- 引用程序集的列表,包括它们的版本和公钥
- 程序集中定义的类型列表
- 它所针对的文化(culture),如果是附属程序集 (AssemblyCulture)
清单还可以存储以下信息数据
- 程序集的完整的标题和描述(AssemblyTitle 和 AssemblyDescription)
- 公司和版权信息(AssemblyCompany 和 Assembly
版权)
- 显示版本(AssemblyInformationalVersion)
- 自定义数据的附加属性
其中一些数据来自提供给编译器的参数,例如引用程序集的列表或用于签署程序集的公钥。其余来自程序集属性,在括号中表示
查看清单内容
您可以使用 .NET 工具 ildasm.exe 查看程序集清单的内容。也可以使用反射以编程方式执行相同的操作
设置程序集属性
常用的程序集属性可以在 Visual Studio 中项目的属性页上的包选项卡(Package tab)上指定。该包选项卡(Package tab)上的设置将被添加到项目文件 (.csproj)。
如果要指定包选项卡不支持的属性,或者如果不使用.csproj 文件,您可以在源代码中指定程序集属性。
.NET Framework项目会在Properties目录自动创建一个文件AssemblyInfo.cs,但 .NET Core 项目没有。
尽管你可以在项目中的任何源代码文件中指定属性,但专门为属性添加一个.cs文件,可以让你把它们放在一起,并且组织得很好。
一个专门的属性文件只包含using语句和汇编属性的声明。例如,为了向一个单元测试项目暴露内部范围的类型。
你应该这样做:
using System.Runtime.CompilerServices;
[assembly:InternalsVisibleTo("MyUnitTestProject")]
应用程序清单(Windows)
应用程序清单是一个XML文件,用于向操作系统传递关于组件的信息。在构建过程中,应用程序清单作为 Win32 资源嵌入到启动可执行文件中。如果清单文件存在,清单会在CLR加载程序集之前被读取和处理,并且会影响Windows启动应用程序进程的方式。
一个.NET应用清单在XML名称空间中具有一个名为assembly的根元素
urn:schemas-microsoft-com:asm.v1:
<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<!-- contents of manifest -->
</assembly>
下面的清单指示操作系统请求管理权限提升:
<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="requireAdministrator" />
</requestedPrivileges>
</security>
</trustInfo>
</assembly>
部署应用程序清单
您可以通过以下方式将应用程序清单添加到 Visual Studio 中的 .NET Core 项目:
在解决方案资源管理器中右键单击您的项目,
选择添加,
然后选择“新建项目”,
然后选择应用程序清单文件
构建后,清单将嵌入到输出程序集中。
.NET 工具 ildasm.exe对嵌入式应用程序清单的存在“视而不见”。但是,如果您在解决方案资源管理器中双击程序集,Visual Studio 会指示是否存在嵌入式应用程序清单
模块(Modules)
程序集的内容实际上打包在一个称为模块的中间容器中。一个模块对应于一个包含程序集内容的文件。
之所以有这个额外的容器层,是为了允许一个程序集跨越多个文件,这个功能在.NETFramework 中存在,但在.NET核心中没有。
尽管 .NET Core 不支持多文件程序集,但有时您需要了解模块带来的额外容器级别。主要场景是有反射的。
装配类(The Assembly Class)
System.Reflection 中的 Assembly 类是在运行时访问程序集元数据的入口(gateway)。
有多种方法可以获得程序集对象:最简单的是通过 Type 的 Assembly 属性
Assembly a = typeof (Program).Assembly;
您还可以通过调用 Assembly 的静态方法之一来获取 Assembly 对象:
GetExecutingAssembly:
返回定义当前执行函数的类型的程序集。
GetCallingAssembly:
与 GetExecutingAssembly 相同,但用于调用当前正在执行的函数的函数。
GetEntryAssembly:
返回定义应用程序原始入口方法的程序集。
拥有 Assembly 对象后,您可以使用其属性和方法来查询程序集的元数据并反射(reflect)其类型
强名称和程序集签名
强命名程序集具有唯一标识。它通过向清单(manifest)添加两位元数据来实现:
- 属于程序集作者的唯一编号
- 程序集的签名哈希,证明唯一编号持有者生成了程序集
这需要公钥/私钥对。公钥提供唯一标识号,私钥便于签名。
公钥在保证程序集引用的唯一性方面很有价值:一个强命名的程序集将公钥合并到它的身份中。
强命名在 .NET Core 中不那么重要,因为 .NET Core 没有全局程序集缓存;也不会限制程序集被其他强命名程序集引用。
如何给Assembly强命名,这里先不讲了,因为在.net core中的作用不大。
程序集名称(Assembly Names)
一个程序集的唯一标识包含来自其清单(manifest)中的四个元数据:
- 它的简单名称(simple name)
- 版本号(默认是"0.0.0.0")
- Its culture (“neutral” if not a satellite)
- 它的公钥令牌(如果没有强命名则为“null”)
这个简单的名字不是来自任何属性,而是来自它最初被编译的文件名(减去任何扩展名)。
因此,System.Xml.dll 程序集的简单名称是“System.Xml”。
重命名文件不会更改程序集的简单名称
版本号来自 AssemblyVersion 属性。它是一个字符串,分为以下四个部分
major.minor.build.revision
您可以如下所示指定版本号:
[assembly: AssemblyVersion ("2.5.6.7")]
区域性来自 AssemblyCulture 属性并应用于附属程序集
The culture comes from the AssemblyCulture attribute and applies to satellite assemblies
正如我们在上一节中讨论的那样,公钥令牌来自编译时提供的强名称
全限定名(Fully Qualified Names)
完全限定的程序集名称是一个包含所有四个标识组件的字符串,格式如下
simple-name, Version=version, Culture=culture, PublicKeyToken=public-key
比如全限定名System.Private.CoreLib.dll 他的简单名称是System.Private.CoreLib,然后Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e。
如上所述,如果有的属性没有值则会被赋为默认值,或为空。
Assembly 对象的 FullName 属性返回其完全限定名称。在清单(manifest)中记录程序集引用时,编译器始终使用完全限定名称文章来源:https://www.toymoban.com/news/detail-764676.html
完全限定的程序集名称不包含有助于在磁盘上定位它的目录路径。定位驻留在另一个目录中的程序集是完全不同的事情。文章来源地址https://www.toymoban.com/news/detail-764676.html
到了这里,关于C#插件式开发——详解程序集Assemblies的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!