14.1. Application Domains

 < Day Day Up > 

When you install .NET on a machine, you create a virtual, managed environment in which applications can run. This environment is designed to insulate applications from the demands and vagaries of the host operating system. The AppDomain is one of the key architectural features supporting the managed environment.

Most operating systems see the world in terms of processes that provide the resources, such as memory and tables required by applications. Because a .NET application cannot run directly in the unmanaged process, .NET partitions a process into one or more logical areas in which assemblies execute. These logical areas are AppDomains. As shown in Figure 14-1, a process may contain more than one AppDomain and an AppDomain may contain one or more assemblies. A default AppDomain is created when the Common Language Runtime (CLR) initializes, and additional ones are created by the CLR as needed. An application may also instruct the CLR to create a new AppDomain.

Figure 14-1. Multiple application domains may reside in a single process

Advantages of AppDomains

Aside from the need for a managed environment, the use of AppDomains provides several advantages over the traditional process-based architecture:

  • Code Isolation. AppDomains institute a level of fault isolation that prevents a code failure in one AppDomain from causing another AppDomain to crash. .NET achieves this code separation in two ways: by preventing an AppDomain from directly referencing objects in another AppDomain, and by having each AppDomain load and maintain its own copy of key assemblies that allow it to run independently. As a by-product of this, an AppDomain can be selectively debugged and unloaded without directly affecting other AppDomains in the process.

  • Performance. Implementing an application to run in multiple AppDomains can produce better performance than a comparable design that relies on multiple processes. This efficiency derives from several factors: A physical process requires more memory and resources than AppDomains, which share the resources of a single process; creating and disposing of processes is much more time consuming than comparable operations on AppDomains; and making a call between processes is slower and requires more overhead than making a call between AppDomains residing in the same process.

  • Security. By its very nature, an AppDomain presents a security boundary between its contained resources and assemblies attempting to access them. To cross this boundary, an outside assembly must rely on remoting, which requires cooperation between the AppDomains. In addition, an AppDomain has its own security policy that it can impose upon assemblies to restrict their permissible operations. This "sandbox" security model allows AppDomains to ensure that assemblies are well behaved. In Chapter 15, "Code Refinement, Security, and Deployment," we'll look at examples of using AppDomains to enforce code security.

Application Domains and Assemblies

When an application runs, it may reference code in several assemblies. By default, the CLR loads these referenced assemblies into the AppDomain of the calling assembly. This means that if a process contains multiple AppDomains that reference the same assembly, a copy of that assembly is placed in each domain. However, it is possible to override the default and share a single assembly among multiple domains. Assemblies used in this manner are referred to as domain-neutral assemblies.

Some crucial assemblies required by all applications are automatically loaded as domain-neutral. The most prominent of these is mscorlib.dll, an assembly that contains the native types integral to the .NET Framework. However, a developer can also specify that a custom assembly be made domain-neutral so that domains can share it.

The use of a domain-neutral assembly saves memory. However, there is a trade-off in terms of performance and flexibility in assigning permissions to assemblies. Even shared assemblies require that their static data and methods be copied into the AppDomains that reference them. The overhead to manage this can slow performance. Only one set of permissions, defining what operations an assembly can perform, can be assigned to domain-neutral assemblies. Thus, if an AppDomain requires a different set of permissions, it must have its own copy of the assembly.

Working with the AppDomain Class

The System.AppDomain class exposes methods and properties that enable an application to create an AppDomain, remove an AppDomain from a process, enumerate the assemblies it contains, and identify itself by name or internal ID. The majority of applications do not require programming at the AppDomain level; however, applications with a need to isolate a custom type library, or include special security features, will find direct interaction with the class a necessity.

In this section, we'll look at an example that illustrates some of the basic techniques used to manipulate an AppDomain. Working though this code should not only make you familiar with the basic class members, but also further clarify the relationship that exists among a process, an AppDomain, and an assembly.

The example defines two classes: RemoteClass, which is compiled into a DLL file, and AppDomainClient, which is compiled into AppdTestClient.exe. RemoteClass is packaged as an assembly that does nothing more than display the name of the domain in which it is running. It uses the static AppDomain.CurrentDomain property to retrieve the current domain, and displays its name using the FriendlyName property.

Note that RemoteClass derives from MarshalByRefObject. As we see in the next section on remoting, this is required if an object is to be accessed from an AppDomain other than its own.

 // AppdTestClass.dll assembly using System; using System.Diagnostics; namespace AppDomainTest {    public class RemoteClass: MarshalByRefObject    {       public void ShowDomain()       {          AppDomain currentAppDomain = AppDomain.CurrentDomain;          Console.WriteLine("Domain:{0}",                     currentAppDomain.FriendlyName);       }    } } 

AppDomainClient, shown in Listing 14-1, illustrates how to use several AppDomain class members. It begins by creating an instance of RemoteClass using the following statement:

 (RemoteClass)currentAppDomain.CreateInstanceAndUnwrap(                    "appdtestclass", "AppDomainTest.RemoteClass"); 

The first parameter is the name of the assembly, and the second is the name of the type being instantiated. This statement returns an object that is cast to an instance of RemoteClass. The object's ShowDomain method is then executed to display the domain it is running in. In this case, the console output is appdtestclient.exe, the default name given to the AppDomain when the assembly is executed. The remainder of the code displays the assemblies in the AppDomain, creates a new AppDomain, and repeats these operations for it.

Listing 14-1. Working with Application Domains
 // AppdTestClient.exe assembly using System; using System.Reflection; using AppDomainTest; public class AppDomainClient {    static void Main()    {       AppDomain currentAppDomain;       currentAppDomain = AppDomain.CurrentDomain;       RemoteClass rc;       // (1) Create instance of RemoteClass       rc=(RemoteClass)currentAppDomain.CreateInstanceAndUnwrap(               "appdtestclass", "AppDomainTest.RemoteClass");       // (2) Execute method on RemoteClass       rc.ShowDomain();       // (3) Show assemblies in this appdomain       Assembly[] currAssemblies =             currentAppDomain.GetAssemblies();       ShowAssemblies (currAssemblies);       // (4) Create a new AppDomain       AppDomain myAppDomain =             AppDomain.CreateDomain("New Domain");       rc=(RemoteClass)myAppDomain.CreateInstanceAndUnwrap(               "appdtestclass", "AppDomainTest.RemoteClass");       rc.ShowDomain();       // (5) Show assemblies in new appdomain       currAssemblies = myAppDomain.GetAssemblies();       ShowAssemblies(currAssemblies);       // (6) The domain a thread runs in can be displayed       Console.Write(             System.Threading.Thread.GetDomain().FriendlyName);       // (7) Unload the new appdomain from the process       AppDomain.Unload(myAppDomain);    }       private static void ShowAssemblies(             Assembly[] currAssemblies)       {          foreach(Assembly a in currAssemblies)          {              Console.WriteLine(                    " Assembly Name: {0}",a.GetName().Name);          }       }    } 

Figure 14-2 shows the three assemblies that exist in the default AppDomain: mscorlib, appdtestclient, and appdtestclass. Mscorlib is automatically loaded by .NET because it contains the System namespace required by the application.

Figure 14-2. AppDomains and assemblies created from code in Listing 14-1

Note that the process also includes a second domain that holds two assemblies. This AppDomain is created using the static CreateDomain method:

 AppDomain myAppDomain = AppDomain.CreateDomain("New Domain"); 

The two assemblies are loaded when AppDomainClient creates an instance of RemoteClass. As you would expect, executing ShowDomain causes the console to display "New Domain" as the name of the current domain.

The final step in the example is to unload the new domain from the process. Note that .NET does not permit an individual assembly to be unloaded from an AppDomain.

     < Day Day Up > 

    Core C# and  .NET
    Core C# and .NET
    ISBN: 131472275
    EAN: N/A
    Year: 2005
    Pages: 219

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net