Assembly Binding Settings
When a strong-named assembly is loaded into an application domain, the default versioning rules provided by the CLR make sure that the exact version of the assembly being referenced is the one that gets loaded. This default behavior lets you enjoy the highest degree of confidence that the application as a whole will run properly because only the set of assemblies that were built and
Although the version policy system is beneficial for the vast majority of application scenarios, I could imagine cases in which the creator of an application domain might want to disable one or more of the available policy levels. The AppDomainSetup object includes two properties that enable you to specify such customizations. The first of these properties, DisallowBindingRedirects , causes all version policy statements made in the application configuration file to be ignored. You might find this property useful to ensure that a consistent set of assemblies is always running in your domain, for example. The second property, DisallowPublisherPolicy , causes all publisher policy statements to be ignored for shared assemblies loaded into the application domain. This property is also used in environments where the creator of the application domain wants very tight control over the versions of the assemblies that are loaded. For example, by using DisallowBindingRedirects and DisallowPublisherPolicy together, the creator of a domain can ensure that only the administrator of the machine is allowed to alter which versions of shared assemblies are loaded into the domain. |
Miscellaneous Settings
There are seven properties of
AppDomainSetup
left to cover. These properties don't fit directly into any of the categories described earlier and are typically used only in very specialized scenarios. It is worth describing them
These miscellaneous properties are LicenseFile, LoaderOptimization, DynamicBase, Disallow-Cod eDownload, ActivationArguments, AppDomainInitializer , and AppDomainInitializerArguments . LicenseFile
The
LicenseFile
property was part of an early design for a licensing model for .NET Framework
LoaderOptimization
The
LoaderOptimization
property is used to configure whether code loaded into an application domain is done so in a domain-neutral fashion. I
DynamicBase
Some applications generate assemblies dynamically using the classes from the
System. Reflection.Emit
namespace or by other means such as simply writing code out to a text file and compiling it. If the dynamically generated assemblies are private to a particular application (that is, they aren't
The CLR
Note
When the DynamicBase and ApplicationName properties are set, the CLR adds a directory of the form
<DynamicBase>\<
random number
>\<ApplicationName>
to the list of directories that are searched when resolving references to private assemblies. Notice that the name of the directory contains a random number. This random number is used to obfuscate the location of the dynamic base a bit so it's not predictable. As a result, the host cannot determine the location in which it can write dynamic assemblies just by remembering the values it specified for DynamicBase and ApplicationName . Instead, a host must use the DynamicDirectory property on System.AppDomain after the application domain has been created to determine where to write its assemblies.
If your application is using the shadow copy feature, the CLR automatically adds the dynamic directory to the list of directories in which files are left unlocked when they are loaded. This feature is
DisallowCodeDownload
The ability to download code dynamically from Web servers onto a client machine is sometimes used to provide a richer
The CLR supports this
ActivationArguments
The .NET Framework 2.0 version of the CLR introduces a new activation model based on applications and components that are defined by an application manifest. This new activation model was initially built to support the ClickOnce deployment model. In ClickOnce, an application manifest provides enough information about the contents and security requirements of the application that the CLR deployment infrastructure can safely download and execute a rich client application over the Web without explicitly installing the application on the client machine. It's likely that application
AppDomainInitializer and AppDomainInitializerArguments
Recall from the discussion of application domain boundaries in Chapter 5 that a good goal to have when designing an application that uses multiple application domains is to keep the communication between the various domains to a minimum. Reducing the amount of crossdomain communication helps improve performance by reducing the number of remote calls that must be made. In addition, applications that limit the number of calls between application domains often have a simpler deployment model because fewer assemblies must be deployed to a location that is visible to all application domains. The
AppDomainInitializer
and
AppDomainInitializerArguments
properties on
AppDomainSetup
help you build applications that minimize cross-domain communication. Oftentimes, the first thing you want to do after creating a new application domain is load an assembly into that domain, instantiate a type from that assembly, and call one of its methods. The
AppDomainInitializer
property enables you to implement this common design pattern with much better performance by eliminating the need for cross-domain calls. Let's look at an example to see how this works. Say we have a human resources application that creates separate application domains in which to load objects that represent
using System;
using System.Reflection;
using HumanResources;
using System.Runtime.Remoting;
namespace AppDomainInit
{
class ADInit
{
[STAThread]
static void Main(string[] args)
{
AppDomain ad = AppDomain.CreateDomain(
"AppDomainInitializer", null, null);
ObjectHandle objHandle = ad.CreateInstance("HumanResources",
"HumanResources.Employee");
Employee e = (Employee) objHandle.Unwrap();
e.Setup();
}
}
}
In this code we create a new application domain and then use the CreateInstance method on System.AppDomain to create a new instance of the Employee type. CreateInstance returns an ObjectHandle that we then unwrap and cast to a local variable of type Employee . Given an object of type Employee , we then call its Setup method to initialize the data for the employee. This code accomplishes what we want it to doit loads a new instance of Employee into the new application domain. However, we pay the cost of several remote calls to accomplish this. Remote calls are involved both in creating the Employee instance and calling it.
The
AppDomainInitializer
and
AppDomainInitializerArguments
properties can be used to accomplish the same end result without the cost of any cross-domain calls. As part of its initialization,
AppDomainInitializer
takes a delegate you supply that the CLR calls from within the new application domain.
AppDomainInitializerArguments
is an array of strings that the CLR
using System;
using System.Reflection;
using HumanResources;
using System.Runtime.Remoting;
namespace AppDomainInit
{
class ADInit
{
static void Initializer(string[] args)
{
Assembly hrAssembly = Assembly.Load(args[0]);
Employee e = (Employee) hrAssembly.CreateInstance(args[1]);
e.Setup();
}
[STAThread]
static void Main(string[] args)
{
AppDomainSetup adSetup = new AppDomainSetup();
adSetup.AppDomainInitializer = new
AppDomainInitializer(ADInit.Initializer);
string[] initializerArgs = new string[2];
initializerArgs[0] = "HumanResources";
initializerArgs[1] = "HumanResources.Employee";
adSetup.AppDomainInitializerArguments = initializerArgs;
AppDomain ad = AppDomain.CreateDomain("AppDomainInitializer",
null, adSetup);
}
}
}
In this example, we create a new application domain, as before, but this time we set the AppDomainInitializer property on AppDomainSetup to the method called ADInit.Initializer and set the AppDomainInitializerArguments to the assembly and the type representing an Employee . As it's setting up the new domain, the CLR calls ADInit.Initializer , passing in the arguments we specified using AppDomainInitializerArguments . ADInit.Initializer then loads the assembly, creates the instance of Employee , and calls its Setup method. Again, the key difference in this second example is that the interaction with the Employee type is all happening from within the new application domain. In this way, no remote calls are needed to set up the Employee type in the new domain.
In some ways, the functionality provided by
AppDomainInitializer
and
AppDomainInitializerArguments
is similar to what can be accomplished using an application domain manager. As discussed in Chapter 5, an application domain manager enables you to initialize new application domains as they are created in the process. I cover this in more detail in the
|