Customizing Application Domain Creation Using System.AppDomainManagerRecall from Chapter 5 that an application domain manager has three primary roles. First, an application domain manager makes it easy to implement the host runtime design pattern for multidomain applications. Second, a domain manager is the means used to communicate between the managed and unmanaged portions of a CLR host. And, finally, application domain managers provide a central point from which you can customize all application domains that are created in a process. It is this last role that I discuss in this section.
Earlier in this chapter, I showed how an instance of
AppDomainSetup
can be passed to
AppDomain.CreateDomain
to customize application domains as they are being created. This approach to customizing application domains works great for the domains you create yourself, but sometimes you might want to have a say in how application domains created by others are customized. A common example of this scenario is that of an extensible application. As the author of an extensible application, you'll likely create several application domains in which to run the add-ins
To understand how this works, take a look at the steps the CLR uses to involve your domain manager when a new domain is
Figure 6-3. Calling an AppDomainManager when a new application domain is created
These steps are described in more detail in the following sections. Step 1: Call AppDomainManager.CreateDomainThe System.AppDomainManager base class contains a virtual CreateDomain method that you can override in your application domain manager to hook all calls to AppDomain.CreateDomain . Whenever AppDomain.CreateDomain is called within a process, the CLR delegates the call to the application domain manager of that process by taking the parameters passed to AppDomain.CreateDomain and passing them to the CreateDomain method on the application domain manager. If you've associated an application domain manager with a process, as discussed in Chapter 5, your domain manager's CreateDomain method is called. If there is no domain manager associated with the process, the implementation of CreateDomain from System.AppDomainManager itself is called. AppDomainManager.CreateDomain has the same method signature as the most commonly used variety of AppDomain.CreateDomain as shown in the following abbreviated class definition:
public class AppDomainManager : MarshalByRefObject
{
public virtual AppDomain CreateDomain (string friendlyName,
Evidence securityInfo,
AppDomainSetup appDomainInfo)
return CreateDomainHelper(friendlyName, securityInfo,
appDomainInfo);
}
By delegating all calls to create an application domain to your domain manager, the CLR provides you with a hook you can use to change any of the parameters passed to
AppDomain.CreateDomain
before the domain is actually created. In this way, you can customize any of the properties on
AppDomainSetup
or change the security evidence or the friendly
You might have noticed that the implementation of
CreateDomain
from the
AppDomainManager
class calls a method named
CreateDomainHelper
.
CreateDomainHelper
is a protected static method on
AppDomainManager
that creates an application domain. It, too, has the same parameters as
AppDomain.CreateDomain
. Typically, the implementation of
CreateDomain
in classes derived from
AppDomainManager
follow a two-step pattern: (1) edit any of the properties on
AppDomainSetup
, the security evidence, or the friendly name to fit your scenario; (2) call
CreateDomainHelper
, passing in your edited values. For example, in Chapter 5 I introduced a fictional CLR host that simulated a sailboat race. This application implemented an application domain manager called
BoatRaceDomainManager
. The add-ins to this host are boats written by third parties. Each boat is loaded into its own application domain. To
We can meet these three requirements by changing some of the properties on the instance of
AppDomainSetup
that we pass on to
CreateDomainHelper
. We can enforce that a boat must be installed to a specific directory by setting that directory as the new domain's
ApplicationBase
. If a boat is not installed in that directory, the CLR will not find the assembly containing the boat when we attempt to load it. We can enforce our last two requirements simply by setting
ShadowCopyFiles
to
false
and
DisallowBindingRedirects
to
true
. The implementation of
CreateDomain
from
BoatRaceDomainManager
is shown in the following code. As discussed, this implementation
public class BoatRaceDomainManager : AppDomainManager, IBoatRaceDomainManager
{
public virtual AppDomain CreateDomain (string friendlyName,
Evidence securityInfo,
AppDomainSetup appDomainInfo)
// Modify the ApplicationBase, ShadowCopyFiles, and
// DisallowBindingRedirects properties.
appDomainInfo.ApplicationBase = @"c:\Program Files\BoatRace\boats";
appDomainInfo.ShadowCopyFiles = "false";
appDomainInfo.DisallowBindingRedirects = true;
return CreateDomainHelper(friendlyName, securityInfo,
appDomainInfo); }
Up until now, we've been
Step 2: Create a New Instance of the Application Domain ManagerIf a new application domain is returned from your application domain manager's implementation of CreateDomain , the CLR creates a new instance of your application domain manager and loads it into the new domain. Step 3: Call AppDomainManager.InitializeNewDomain
After loading an instance of the application domain manager into the new domain, the CLR calls its
InitializeNewDomain
method.
InitializeNewDomain
gives you a chance to do any further application domain configuration while running within the new domain. By implementing an application domain manager, you are given two
At first glance it might seem that
CreateDomain
and
InitializeNewDomain
are just two different ways of doing exactly the same thing. Although it is true that both enable you to customize the new domain, a few subtleties justify having both
In contrast,
InitializeNewDomain
is useful for doing the type of initializations that can be accomplished more
InitializeNewDomain takes an instance of AppDomainSetup as shown in the following definition from the AppDomainManager base class:
public class AppDomainManager : MarshalByRefObject
{
public virtual void InitializeNewDomain (AppDomainSetup appDomainInfo)
{
}
}
Although the application domain is partially
public class BoatRaceDomainManager : AppDomainManager, IBoatRaceDomainManager
{
public virtual void InitializeNewDomain (AppDomainSetup appDomainInfo)
{
if (IsDefaultAppDomain())
appDomainInfo.ApplicationBase = @"c:\Program Files\BoatRace";
}
}
Step 4: Get the ApplicationActivator
After
CreateDomain
and
InitializeNewDomain
are called, the CLR takes three objects from your application domain manager that you can provide to customize other aspects of how the new application domain will work. The CLR obtains these objects through public properties on your application domain manager class. The first of these three properties is
ApplicationActivator
. The
ApplicationActivator
property returns an object of type
ApplicationActivator
that you can use to customize how applications defined by
Step 5: Get the HostExecutionContextManager
The
Step 6: Get the HostSecurityManager
The last object the CLR gets from your application domain manager is of type
HostSecurityManager
. The CLR
|