Chapter 1. CLR
and Other Extensible Applications
The Common Language Runtime (CLR) lies at the heart of the Microsoft .NET initiative. It is the CLR that provides the runtime services required to execute the code you write to expose as Web services, Microsoft ASP.NET applications, rich client applications, database stored procedures, and so on. If you've worked much with the .NET Framework, you're probably familiar with many of the high-level benefits of the CLR, such as automatic memory management (garbage collection), the common type system, and Code Access Security (CAS). However, the CLR possesses another key characteristic that you might not have spent as much time working with directly: its tremendous flexibility.
The extensibility points
by the CLR enable it to be customized to run in a variety of application environments that have a wide range of requirements. For example, these extensibility points have enabled the CLR to be integrated into Microsoft SQL Server 2005, Internet Information Services (in the form of ASP.NET), and the Internet Explorer Web browser, among others. The ability of a
runtime system to be customized so extensively is crucial for a platform to achieve broad adoption. Imagine how differently the .NET Framework would be perceived if it were only a platform that supported rich client applications or Web applications, but not both, or if it supported the application models developed by Microsoft, but didn't allow third parties to develop their own. The absence of extensibility severely limits the reach of a platform. The CLR's flexibility has been a key factor in the overall success of the .NET Framework to date.
This book describes how to use the various extensibility points provided by the CLR to customize it to work well in your particular application. Almost every major subsystem of the CLR is customizable. For example, the CLR has a
set of default rules it uses to locate assemblies that are referenced within an application. However, although these default rules can work great in many scenarios, it's clear that one model cannot
the requirements of every application. In light of that problem, the CLR allows the rules for loading assemblies to be customized completely.
In a similar way, the .NET Framework ships with a default policy that governs the security permissions granted to applications running on a particular machine. Again, if this default policy doesn't meet your needs, you're free to define programmatically your own policy that can directly affect the permissions granted to the code running in your process. The release of the CLR included in Microsoft .NET Framework 2.0 dramatically
the amount of customization possible. Many of the new ways you can customize the CLR result from the work done to integrate the CLR into SQL Server 2005 and into future versions of the Microsoft Windows operating system. The customization available in .NET Framework 2.0 is so
that you can even replace the basic primitives the CLR uses to allocate memory, create threads, and so on. In essence, the .NET Framework 2.0 CLR enables you to substitute your own mechanism for providing basic services for which the CLR typically relies on the operating system. In this way, you can achieve a high degree of integration between your application and the CLR.
This book covers a variety of topics,
from how to make the most effective use of application domains to how to replace the basic primitives used for memory allocation. Many of the customizations covered can be accomplished directly from within your managed application. However, some CLR customization scenarios require the use of unmanaged code. In most cases, unmanaged code is required for two main types of customizations: those that must take place before the CLR begins executing managed code, such as the selection of which version of the CLR to use; and those that require a deep integration with the CLR engine, such as the ability to customize the format in which assemblies are stored.
The CLR provides an unmanaged collection of functions and interfaces called the
CLR hosting APIs
for those times when you must customize the CLR from unmanaged code.
speaking, applications that are written to take advantage of the CLR hosting APIs can customize the CLR to a much greater extent than those applications written completely in managed code. The applications that take advantage of the CLR hosting APIs are called
. CLR hosts are a specific example of an
. In the context of this book, an extensible application is any application that defines an extensibility model that allows
to be loaded dynamically into its process. Following are a few concrete examples of extensible applications:
Today's database servers provide extensibility models that enable developers to add custom code to the database in a variety of ways. Stored procedures,
-defined types, and custom aggregate functions are all ways to extend the built-in functionality of the database. The database server is the extensible application, and the stored procedures, types, and so on defined by the third-party developer are the add-ins.
Historically, Web browsers have included an extensibility model that allows custom code to run when a Web page is accessed. For example, many Web browsers include a Java Virtual Machine that allows Java applets to be loaded and run dynamically. Also, Microsoft Internet Explorer supports add-ins in the form of controls written with the .NET Framework.
ASP.NET is a great example of an application environment that provides an extensibility model for Web servers. ASP.NET enables developers to write custom application code that is hosted on the Web server. In this example, the code that is written as part of the Web application serves as the add-in.
Many productivity applications offer extensibility models. For example, most e-mail programs now allow custom code to be executed when various events, such as the sending and receiving of e-mail, occur. Similarly, many word processors, spreadsheet programs, and other client-side applications allow users to write add-ins to add dynamic behavior to documents. In some cases, the extensibility model provided by these applications is so extensive that the program almost becomes a programming environment in itself.
A key property of extensible applications is that they are dynamic. In particular, the set of add-ins that will be loaded into the extensible application is determined dynamically instead of when the application is built, which means, in part, that the number of add-ins that will be loaded and where they will come from is unknown. These characteristics result in some unique requirements in many areas, including security, assembly loading, and reliability. For example, the fact that add-ins can come from unknown sources generally requires the authors of extensible applications to take a conservative approach to security. Also, the individual add-ins in an extensible application often are isolated to ensure that unrelated add-ins cannot interfere with each other. Many of the topics I discuss in this book are aimed at solving the problems
in extensible applications. As you'll see, the CLR allows itself to be customized in a variety of ways that help it adapt to the unique requirements of extensible applications, including CLR hosts.
Most extensible applications have several common architectural
as shown in Figure 1-1.
Figure 1-1. Common elements of an extensible application
I use the basic architectural framework in Figure 1-1 throughout the book as I describe the various CLR customizations from within the context of extensible applications. The key architectural elements of an extensible application include the following:
Add-ins are the extensions that are dynamically added to your application. Because add-ins often come from unknown origins and the set of add-ins you'll load is determined dynamically, applications that provide an extensibility model have unique requirements as described earlier. Examples of add-ins include stored procedures in SQL Server 2005, Web pages containing code in ASP.NET, and controls loaded in a Web browser.
An application domain is a construct used to isolate groups of assemblies running within an operating system process. Extensible applications typically use application domains to make sure that unrelated add-ins can't interfere with each other. Several application domains can exist in a given process
. As you'll see, application domains provide many benefits of process-based isolation at a much lower cost.
Application domain manager
The .NET Framework 2.0 release of the CLR includes a new concept called an application domain manager that makes it much easier to write applications that use multiple application domains. As the author of an extensible application, you provide a class that derives from an application domain manager base class, and the CLR takes care of automatically creating an instance of your domain manager in each new application domain created. This infrastructure enables you to load assemblies into application domains much more
and to configure the various settings that control how application domains behave within your process.
In many ways, writing a CLR host (or any extensible application) defines a new application model in which managed code can be run. For example, without the SQL Server 2005 host, stored procedures could not be written in managed code. Similarly, without the integration of the CLR with Internet Explorer using the CLR hosting API, browser controls written with .NET Framework could not be used in Web pages. Both of these application models are examples that leverage the techniques described in this book to enable managed code to be used in many more scenarios. Each new effectively written CLR host extends the reach of the .NET platform.