《.NET程序员面试秘笈》----面试题14 简述程序集和应用程序域

简介: 【考点】.NET程序集的知识,.NET应用程序域的理解,.NET应用程序域与程序集的简单应用

本节书摘来自异步社区《.NET程序员面试秘笈》一书中的第1章,面试题14,作者: 张云翯, 更多章节内容可以访问云栖社区“异步社区”公众号查看。

面试题14 简述程序集和应用程序域

.NET程序员面试秘笈
【考点】.NET程序集的知识,.NET应用程序域的理解,.NET应用程序域与程序集的简单应用。

【出现频率】

【解答】

.NET的程序集用于解决DLL HELL,DLL HELL是指与DLL有关的问题。程序集是自我描述的安装单元,这是一个逻辑单元,而非一个文件。程序集可以是包含元数据的多个文件,也可以是一个DLL或EXE文件。简而言之,程序集是作为整体发布的.NET可执行程序或.NET可执行程序的一部分,包含了程序的文件集或资源文件。

程序集分为私有程序集和共享程序集,私有程序集是创建.NET项目时默认的,也是比较常用的方式。私有程序集以可执行文件或库的形式提供应用程序,库中的代码只服务于这个应用程序。而共享程序集是一个公共库,可服务于系统中所有程序。共享程序集必须安装到.NET的特别目录中,而其他被服务的程序则不需要知道安装的地方。

【分析】

任何.NET程序均由程序集构成,程序集是包含已编译的、面向.NET Framework的代码的逻辑单元。当程序集存储于多个文件当中时,则一定有一个主文件包含程序集主程序的入口,这个包含入口的主文件描述了位于相同程序集的其他文件。程序集包含描述自身的元数据,这种元数据位于程序集清单中,可用于检查版本以及自身的完整性。

说明:

动态程序集位于内存中,而非存储于文件中。
应用程序域是.NET中的程序的“边界”。相对于进程边界,应用程序域边界范围更小。在Windows 7/XP中,进程可以有效保证不同的程序安全地运行,当某个程序出错时并不会影响其他程序。但是进程对多程序运行的系统性能作出了妥协,因为进程之间不允许共享内存。可以使用基于DLL的组件解决这个问题,将所有的DLL组件在一个地址空间中运行,不过当某个组件出错时将会影响其他组件。使用应用程序域可以分离组件,并且不会导致类似于进程的性能问题。

说明:

进程有独立的虚拟内存,以保证进程之间的内存无法互写。
在一个进程内可容纳多个应用程序域,这样,.NET中的应用程序域可使多个应用程序运行于同一个进程。在没有代理的情况下,不同的应用程序域中的实例和静态成员无法共享,这样也保证了安全性。

说明:

程序集的代码只需加载一次,以减少内存消耗。
本例展示了程序集和应用程序域的简单应用。在VS环境(VS2008或VS2010)中创建一个新控制台应用程序,名称为AppA,在Program.cs中编写代码如程序1.16所示。

程序1.16 AppA项目:Program.cs

  using System;
  using System.Collections.Generic;
  using System.Text;
  namespace AppDomainTest
  {
    class Program
    {
      static void Main(string[] args)
      {
        //创建AppDomain类型的current,用于引用AppDomain.CurrentDomain
        AppDomain current = AppDomain.CurrentDomain;
        //输出程序的应用程序域的名称
        Console.WriteLine("大家好,我是程序集AppA,我所在的应用程序域是{0}。", current.FriendlyName);
      }
    }
  }

执行本程序,可得到结果如图1.22所示。


e97b208f5898591f2954b4e801e55a95a0445156

可见,当应用程序运行时,默认所在的应用程序域的名称为程序名称。现在AppA项目已经编译了最简单的私有程序集,位于ch01AppAAppAbinDebug目录下。接下来用同样的方法在VS环境中创建新项目,名称为AppB,在其Program.cs中编写代码如程序1.17所示。

程序1.17 AppB项目:Program.cs

  using System;
  using System.Collections.Generic;
  using System.Text;
  namespace AppDomainTest
  {
    class Program
    {
      static void Main(string[] args)
      {
        //创建AppDomain类型的one,用于引用AppDomain.CurrentDomain
        AppDomain one = AppDomain.CurrentDomain;
        //输出one的基目录以及名称、上下文信息
        Console.WriteLine("大家好,我是程序集B,我的基目录:{0}\n我所在的应用程序域的名称及上下文策略:{1}", one.BaseDirectory, one.ToString());
        //在当前的应用程序域中加载程序集AppA.exe
        one.ExecuteAssembly("AppA.exe");
        Console.WriteLine("\n上面的AppA程序集和下面的AppA程序集位于不同的应用程序域\n");
        //创建AppDomain类型的tow,用于引用AppDomain类创建的新应用程序域,其名称为ROOM-A
        AppDomain two = AppDomain.CreateDomain("ROOM-A");   
        //two应用程序域装载(执行)AppA.exe程序集
        two.ExecuteAssembly("AppA.exe");
        //输出two的基目录以及名称、上下文信息
        Console.WriteLine("AppA程序集的基目录:{0}\nAppA程序集所在的应用程序域的名称及上下文策略:{1}", two.BaseDirectory, two.ToString());
      }
    }
  }

执行程序前,首先需添加程序集引用,在VS中的菜单栏中单击“项目|添加引用”,在添加引用的对话框中单击“浏览”选项,如图1.23所示。

浏览AppA项目的程序集路径,即ch01AppAAppAbinDebug目录,选中AppA.exe,单击“确定”按钮即可。这步的操作实际上把AppA程序集直接复制到AppB项目程序集的相同目录下,即复制到ch01AppBAppBbinDebug目录下。这也充分展示了私有程序集安装的便捷性,现在,AppB应用程序执行时即可将AppA程序集装载到新建的应用程序域了。执行AppB项目的程序,可得到结果如图1.24所示。


c3c2bda07c50e7c8fd738e97d838557a591da258

如图所示,AppA程序集首先被加载到当前应用程序域,然后被加载到名称为“ROOM-A”的应用程序域中。从任务管理器中观察,AppA程序集并没有创建新的进程。AppB程序集所在的应用程序域被称为进程中的主应用程序域,这是运行时自动创建的。

说明:

实际上AppA程序集已加载到AppB.exe进程中运行,这就达到了多个应用程序在同一个进程中运行的目的。
本节问题相对比较靠近.NET的底层,编程者必须理解程序基本的运行过程,才能写出更高效的程序。从本节的代码中可知,AppDomain类用于创建和中断应用程序域,加载和卸载程序集合类等功能,另外AppDomain类还可以枚举应用程序域中的程序集和线程。由于程序集包含了元数据,其中含有所有定义的类型以及这些类型成员的细节,所以可通过反射技术来获取这些数据。

本节示例主要展示了应用程序域的简单使用,其“边界”作用不同于进程,不同应用程序域中的应用程序有自己独立的内存空间。在默认情况下,这些程序互相隔离,保证程序安全运行。示例中AppB.exe程序运行情况如图1.25所示。


895b06d5282875e496edbda0839c2462fd9556bb

本文仅用于学习和交流目的,不代表异步社区观点。非商业转载请注明作译者、出处,并保留本文的原始链接。

相关文章
|
3月前
|
存储 Shell Linux
快速上手基于 BaGet 的脚本自动化构建 .net 应用打包
本文介绍了如何使用脚本自动化构建 `.net` 应用的 `nuget` 包并推送到指定服务仓库。首先概述了 `BaGet`——一个开源、轻量级且高性能的 `NuGet` 服务器,支持多种存储后端及配置选项。接着详细描述了 `BaGet` 的安装、配置及使用方法,并提供了 `PowerShell` 和 `Bash` 脚本实例,用于自动化推送 `.nupkg` 文件。最后总结了 `BaGet` 的优势及其在实际部署中的便捷性。
181 10
|
20天前
|
算法 Java 测试技术
Benchmark.NET:让 C# 测试程序性能变得既酷又简单
Benchmark.NET是一款专为 .NET 平台设计的性能基准测试框架,它可以帮助你测量代码的执行时间、内存使用情况等性能指标。它就像是你代码的 "健身教练",帮助你找到瓶颈,优化性能,让你的应用跑得更快、更稳!希望这个小教程能让你在追求高性能的路上越走越远,享受编程带来的无限乐趣!
68 13
|
1月前
|
开发框架 监控 .NET
【Azure App Service】部署在App Service上的.NET应用内存消耗不能超过2GB的情况分析
x64 dotnet runtime is not installed on the app service by default. Since we had the app service running in x64, it was proxying the request to a 32 bit dotnet process which was throwing an OutOfMemoryException with requests >100MB. It worked on the IaaS servers because we had the x64 runtime install
|
1月前
|
JSON 算法 安全
JWT Bearer 认证在 .NET Core 中的应用
【10月更文挑战第30天】JWT(JSON Web Token)是一种开放标准,用于在各方之间安全传输信息。它由头部、载荷和签名三部分组成,用于在用户和服务器之间传递声明。JWT Bearer 认证是一种基于令牌的认证方式,客户端在请求头中包含 JWT 令牌,服务器验证令牌的有效性后授权用户访问资源。在 .NET Core 中,通过安装 `Microsoft.AspNetCore.Authentication.JwtBearer` 包并配置认证服务,可以实现 JWT Bearer 认证。具体步骤包括安装 NuGet 包、配置认证服务、启用认证中间件、生成 JWT 令牌以及在控制器中使用认证信息
102 2
|
2月前
|
SQL XML 关系型数据库
入门指南:利用NHibernate简化.NET应用程序的数据访问
【10月更文挑战第13天】NHibernate是一个面向.NET的开源对象关系映射(ORM)工具,它提供了从数据库表到应用程序中的对象之间的映射。通过使用NHibernate,开发者可以专注于业务逻辑和领域模型的设计,而无需直接编写复杂的SQL语句来处理数据持久化问题。NHibernate支持多种数据库,并且具有高度的灵活性和可扩展性。
47 2
|
2月前
|
开发框架 .NET API
Windows Forms应用程序中集成一个ASP.NET API服务
Windows Forms应用程序中集成一个ASP.NET API服务
109 9
|
3月前
|
数据采集 JSON API
.NET 3.5 中 HttpWebRequest 的核心用法及应用
【9月更文挑战第7天】在.NET 3.5环境下,HttpWebRequest 类是处理HTTP请求的一个核心组件,它封装了HTTP协议的细节,使得开发者可以方便地发送HTTP请求并接收响应。本文将详细介绍HttpWebRequest的核心用法及其实战应用。
164 6
|
3月前
|
算法 程序员 Go
PHP 程序员学会了 Go 语言就能唬住面试官吗?
【9月更文挑战第8天】学会Go语言可提升PHP程序员的面试印象,但不足以 solely “唬住” 面试官。学习新语言能展现学习能力、拓宽技术视野,并增加就业机会。然而,实际项目经验、深入理解语言特性和综合能力更为关键。全面展示这些方面才能真正提升面试成功率。
63 10
|
2月前
|
XML 存储 安全
C#开发的程序如何良好的防止反编译被破解?ConfuserEx .NET混淆工具使用介绍
C#开发的程序如何良好的防止反编译被破解?ConfuserEx .NET混淆工具使用介绍
116 0
|
3月前
|
Ubuntu 持续交付 API
如何使用 dotnet pack 打包 .NET 跨平台程序集?
`dotnet pack` 是 .NET Core 的 NuGet 包打包工具,用于将代码打包成 NuGet 包。通过命令 `dotnet pack` 可生成 `.nupkg` 文件。使用 `--include-symbols` 和 `--include-source` 选项可分别创建包含调试符号和源文件的包。默认情况下,`dotnet pack` 会先构建项目,可通过 `--no-build` 跳过构建。此外,还可以使用 `--output` 指定输出目录、`-c` 设置配置等。示例展示了创建类库项目并打包的过程。更多详情及命令选项,请参考官方文档。
246 11

热门文章

最新文章