前面已经讨论了宿主以及宿主加载CLR的方式。同时还讨论了宿主如何告诉CLR创建和卸载AppDomain。为了使这些讨论更加具体,下面将描述一些常见的宿主和AppDomain使用情形。特别地,我要解释不同应用程序类型如何宿主CLR,以及他们如何管理AppDomain。
1 可执行应用程序
控制台UI应用程序、NT Service应用程序、Windows窗体应用程序和WPF应用程序都是自宿主应用程序的例子,他们都有托管的EXE文件。Windows用一个托管EXE文件初始化一个进程时,会加载垫片。垫片会检查包含在应用程序的程序集中的CLR头信息。头信息指明生成和测试应用程序时使用的CLR的版本。垫片根据这个信息决定将哪个版本的CLR加载到进程中,CLR加载并初始化好之后,它会检查程序集的CLR头,判断应用程序的入口方法是哪个(Main)。CLR调用这个方法。在这个时候,应用程序会真正启动并运行。
代码运行时,它会访问其他类型。引用另一个程序集中的类型时,CLR会定为所需程序集,并把它加载到同一个AppDomain中。应用程序的Main方法返回后,Windows进程终止(销毁默认AppDomain和其他所有AppDomain).
注意:顺便说一句,如果想关闭Window进程(包括它的所有AppDomain),可调用System.Environment的静态方法Exit,该方法时终止进程最得体的方式,因为它首先调用托管堆上的所有对象的Finalize方法,然后释放由CLR持有的所有非托管COM对象。最后,Exit调用Win32的ExitProcess函数。
应用程序可告诉CLR在进程的地址空间中创建额外的AppDomain。
2.Silverlight富Internet应用程序
Microsift的Silverlight”运行时”技术采用了和.NET FrameWork的普通桌面版本有所区别的一个特殊CLR。安装好Silverlight”运行时”之后,每次访问使用了Silverlight技术的一个网站,都会造成Silverlight CLR(CoreClr.dll)加载到浏览器中(这可能是、也可能不是IE-甚至不一定是一台Windows机器)。网页上的每个Silverlight控件都在它自己的AppDomain中运行。用户关闭一个标签页,或切换至另一个网站时,不再使用的任何Silverlight控件的AppDomain都会卸载。AppDomain中的Silverlight代码在一个安全性受到限制的沙箱中运行,不会以任何方式对用户或机器造成损害
3.ASP.NET Web窗体和XML Web服务器应用程序
ASP.NET 作为一个ISAPI DLL(ASPNet_ISAPI.dll)实现。客户首次请求一个由ASP.NET ISAPI DLL处理的URL时,ASP.NET会加载CLR。客户端请求一个Web应用程序时,ASP.NET判断这是不是第一次请求。如果是,ASP.NET会告诉CLR为该Web应用程序创建一个新的AppDomain每个Web应用程序都按照它的虚拟根目录来标识。然后,ASP.NET指示CLR将包含了“应用程序所公开的类型”的程序集加载到新AppDomain中,创建该类型的一个实例,并调用其中的方法响应客户端的Web请求。如果代码引用了更多类型,CLR会将所需的程序集加载到Web应用程序的AppDomain中。
未来的客户端请求一个已开始运行的Web应用程序时,ASP.NET不再创建AppDomain;相反,它会使用现在AppDomain,创建Web应用程序的类型的一个新实例,并开始调用方法。这些方法已JIT编译成本地代码,所以后续客户端请求的处理性能将会比较出色。
如果客户端请求一个不同Web应用程序,ASP.NET会告诉CLR创建一个新AppDomain。新AppDomain通常在和其他AppDomain一样的工作进程中创建。这意味着许多Web应用程序在同一个Window进程中运行,这提升了整体系统的总体效率。同样地,每个Web应用程序需要的程序集都会加载到一个单独的AppDomain中,这个AppDomain唯一的目的就是讲Web应用程序的代码和其他Web应用程序隔离。
ASP.NET的另一个出色的功能就是可以在不关闭Web服务器的前提下动态更改网站的代码。网站的文件在硬盘上发生改动时,ASP.NET会检测到这个情况,并卸载包含旧版本文件的AppDomain,并创建一个新AppDomain,向其中加载新版本的文件。为了确保这个过程的顺利进行,ASP.NET 使用了AppDomain的一个名为”影像复制”的功能。
4. Sql Server
Microsoft SQL Server是一个非托管的应用程序,因为它的大部分代码仍是用非托管C++写的。Sql Server允许开发人员通过托管代码创建存储过程。首次请求数据库运行一个用托管代码写的存储过程时,SQL SERVER会加载CLR。存储过程在它们自己的安全AppDomain中运行,这避免了存储过程对数据库服务器产生负面影响。
这其实是一项非同寻常的功能!这意味着开发人员可以选择自己喜欢的编程语言来编写存储过程。存储过程可以在自己的代码中使用强类型的数据对象。代码还会被JIT编译成本地代码,而不是采用解析执行的方式。开发人员可利用FCL或任何其他程序集定义的任何类型。结果是我们的工作边的越来越轻松,但应用程序执行的越来越好。
5. 更多的用法只局限于你自己的想象力
生产性应用程序(比如字处理软件和电子表格软件)也允许用户使用任何编程语言来编写宏。宏可以访问与CLR一起运行的所有程序集和类型。这些宏将被编译,因为他们执行的更快。而且最重要的是,这些宏将在一个安全AppDomain中运行,避免对任何用户产生不利影响。你自己的应用程序也可利用这个功能。具体怎么用,只局限于你自己的想象力。