The preceding descriptions of isolation have centered on preventing applications that are already running from seeing or manipulating each other's memory space or other resources. An equally important aspect of isolation is the ability to allow an application to control where the NGWS runtime finds code to load on its behalf. This is important to prevent code placed on the machine by one application from inadvertently affecting other applications.
The ability to scope resolution requests by application differs significantly from the way the current platform works. In Windows today, the resolution scope is effectively "the machine" in that any application can use any code as long as its described in the registry or placed in a well known location like the Windows system directory. In fact, sharing in this manner is the default - there is no way for an application to explicitly describe its pieces, their dependencies, and where to find them. This behavior of default sharing leads to the dll conflicts that user's of our platform experience today.
In addition to scoping requests to load code, it is also important to scope configuration information to an application. For many configuration settings, this isn't possible today. For example, consider the case of configuring the remote machine on which to run an NGWS class. Setting the RemoteServerName key in the registry for a particular class affects all applications that use that class. As with unintended sharing or code, the unintended sharing of configuration data prevents an application from having complete control over its own behavior.
A key goal of the deployment features in the NGWS runtime is to provide the form of application scoping described above. To provide this form of isolation, each assembly must be able to explicitly express dependencies on the other assemblies it uses. This dependency information must include version requirements so the NGWS runtime can load the appropriate version of the dependency. This information is captured in the assembly's manifest. For all references made from the current assembly, the information in the manifest is used to govern how the reference is resolved. There are three cases of interest:
While the information in the assembly manifest describes the versions of the assembly's dependencies, it doesn't provide any explicit information about how to locate the assembly. Specifically, manifests do not record dependencies between assembly in terms of paths or filenames. The information about where to look for assemblies can be controlled by the Application Domain. In addition, the Application Domain also provides the configuration information to be used by code running in that domain.
More accurately, search rules and configuration data is provided by the host when the application domain is created. The host is responsible for supplying this data because the meaningful values vary by scenario. For example, the configuration data for ASP+ applications is stored per application, site and machine, while the configuration data for an exe is stored per application, user and machine. Only the host knows the specifics of the configuration data for their particular scenario.
In terms of searching information, the host provides a search path when creating the Application Domain. This path is used to find dependent assemblies that are deployed in subdirectories underneath the application. These assemblies are typically private assemblies, but shared assemblies can be deployed here as well. Note that for shared assemblies, the NGWS runtime will always look in the global assembly cache as well as on the search path.
In addition, the configuration information supplied with the domain may provide explicit information about where to find particular assemblies. The path is supplied using the appropriate parameter to AppDomain::CreateDomain:
public static AppDomain CreateDomain( string friendlyName, IIdentity[] securityInfo, ContextPolicy[] policies, // optional string AppRelativeSearchPath, // optional boolean ShadowCopyFiles, // optional long SnapshotID);
The combination of the dependency information captured as part of each assembly manifest and the searching and configuration data maintained by the domain, provide the information that the NGWS runtime uses to properly scopes requests to load code and to access configuration data to a particular application. The following diagram summaries where each piece of information is stored in a running domain: