.Net Framework, Asp.net, Ado.net, .Net Remoting, .Net Webservice, SQL, XML, XSLT, WCF, WPF, WWF NHibernate, Ajax, Jquery, DHTML

Ado.netAsp.Net 2.0SQLC-SharpXMLFrameworkIISXMLWebServiceArchitecture
UMLProject ManagementSDLCMethodologiesDesign PatterenOOPWCF.Net RemotingWWF
MVPMVCSilver LightN-HibernateAjaxJ-QuerySEO-MarketingSite MapPhp

.Net Framework

.Net Framework 2.0.Net Framework 3.0.Net Framework 3.5
.net FrameworkMetadata .netManifest in .net
DLL Hell Problem in .netShared Assembly in .net


Versioning and Sharing

One of the primary causes of DLL Hell is the sharing model currently used in component-based systems. By default, individual software components are shared by multiple applications on the machine. For example, every time an installation program copies a DLL to the system directory or registers a class in the COM registry, that code will potentially have an effect on other applications running on the machine. In particular, if an existing application used a previous version of that shared component, that application will automatically start using the new version. If the shared component is strictly backward compatible this may be okay, but in many cases maintaining backward compatibility is difficult, if not impossible. If backward compatibility is not maintained, or cannot be maintained, this often results in applications that are broken as a side effect of other applications being installed.

A principle design guideline in .NET is that of isolated components (or assemblies). Isolating an assembly means that an assembly can only be accessed by one application—it is not shared by multiple applications on the machine and cannot be affected by changes made to the system by other applications. Isolation gives a developer absolute control over the code that is used by his application. Isolated, or application-private, assemblies are the default in .NET applications. The trend toward isolated components started in Microsoft Windows 2000 with the introduction of the .local file. This file was used to cause both the OS Loader and COM to look in the application directory first when trying to locate the requested component. (See the related article in the MSDN Library, Implementing Side-by-Side Component Sharing in Applications.)

However, there are cases where sharing an assembly between applications is necessary. It clearly wouldn't make sense for every application to carry its own copy of System.Windowns.Forms, System.Web or a common Web Forms control.

In .NET, sharing code between applications is an explicit decision. Assemblies that are shared have some additional requirements. Specifically, shared assemblies should support side by side so multiple versions of the same assembly can be installed and run on the same machine, or even within the same process, at the same time. In addition, shared assemblies have stricter naming requirements. For example, an assembly that is shared must have a name that is globally unique.

The need for both isolation and sharing leads us to think of two "kinds" of assemblies. This is a rather loose categorization in that there are no real structural differences between the two, but rather the difference is in how they will be used: whether private to one application or shared among many.

Application-Private Assemblies

An application-private assembly is an assembly that is only visible to one application. We expect this to be the most common case in .NET. The naming requirements for private assemblies are simple: The assembly names must only be unique within the application. There is no need for a globally unique name. Keeping the names unique isn't a problem because the application developer has complete control over which assemblies are isolated to the application.

Application-private assemblies are deployed within the directory structure of the application in which they are used. Private assemblies can be placed directly in the application directory, or in a subdirectory thereof. The CLR finds these assemblies through a process called probing. Probing is simply a mapping of the assembly name to the name of the file that contains the manifest.

Specifically, the CLR takes the name of the assembly recorded in the assembly reference, appends ".dll" and looks for that file in the application directory. There are a few variants on this scheme where the Runtime will look in subdirectories named by the assembly or in subdirectories named by the culture of the assembly. For example, a developer may choose to deploy the assembly containing resources localized to German in a subdirectory called "de" and to Spanish in a directory called "es." (See the .NET Framework SDK Guide for details.)

As just described, each assembly manifest includes version information about its dependencies. This version information is not enforced for private assemblies because the developer has complete control over the assemblies that are deployed to the application directory.

Shared Assemblies

The .NET Framework also supports the concept of a shared assembly. A shared assembly is one that is used by multiple applications on the machine. With .NET, sharing code between applications is an explicit decision. Shared assemblies have some additional requirements aimed at avoiding the sharing problems we experience today. In addition to the support for side by side describe earlier, shared assemblies have much more stringent naming requirements. For example, a shared assembly must have a name that is globally unique. Also, the system must provide for "protection of the name"—that is, preventing someone from reusing another's assembly name. For example, say you're a vendor of a grid control and you've released version 1 of your assembly. As an author you need assurance that no one else can release an assembly claiming to be version 2 or your grid control. The .NET Framework supports these naming requirements through a technique called strong names (described in detail in the next section).

Typically, an application author does not have the same degree of control over the shared assemblies used by the application. As a result, version information is checked on every reference to a shared assembly. In addition, the .NET Framework allows applications and administrators to override the version of an assembly that is used by the application by specifying version policies.

Shared assemblies are not necessarily deployed privately to one application, although that approach is still viable, especially if xcopy deployment is a requirement. In addition to a private application directory, a shared assembly may also be deployed to the Global Assembly Cache or to any URL as long as a codebase describing the location of the assembly is supplied in the application’s configuration file. The global assembly cache is a machine-wide store for assemblies that are used by more than one application. As described, deploying to the cache is not a requirement, but there are some advantages to doing so. For example, side-by-side storage of multiple versions of an assembly is provided automatically. Also, administrators can use the store to deploy bug fixes or security patches that they want every application on the machine to use. Finally, there are a few performance improvements associated with deploying to the global assembly cache. The first involves the verification of strong name signatures as described in the Strong Name section below. The second performance improvement involves working set. If several applications are using the same assembly simultaneously, loading that assembly from the same location on disk leverages the code sharing behavior provided by the OS. In contrast, loading the same assembly from multiple different locations (application directories) will result in many copies of the same code being loaded. Adding an assembly to the cache on an end user's machine is typically accomplished using a setup program based on the Windows Installer or some other install technology. Assemblies never end up in the cache as a side effect of running some application or browsing to a Web page. Instead, installing an assembly to the cache requires an explicit action on the part of the user. Windows Installer 2.0, which ships with Windows XP and Visual Studio .NET, has been enhanced to fully understand the concept of assemblies, the assembly cache and isolated applications. This means you will be able to use all of the Windows Installer features, such as on-demand install and application repair, with your .NET applications.

It’s often not practical to build an install package every time you want to add an assembly to the cache on development and test machines. As a result, the .NET SDK includes some tools for working with the assembly cache. The first is a tool called gacutil that allows you to add assemblies to the cache and remove them later. Use the /i switch to add an assembly to the cache:

gacutil /i:myassembly.dll 
See the .NET Framework SDK documentation for a full description of the 
      options supported by gacutil.

The other tools are a Windows Shell Extension that allows you to manipulate the cache using the Windows Explorer and the .NET Framework Configuration Tool. The Shell Extension can be accessed by navigating to the "assembly" subdirectory under your Windows directory. The .NET Framework Configuration Tool can be found in the Administrative Tools section of the Control Panel.

Strong names

Strong names are used to enable the stricter naming requirements associated with shared assemblies. Strong names have three goals:

  • Name uniqueness. Shared assemblies must have names that are globally unique.
  • Prevent name spoofing. Developers don't want someone else releasing a subsequent version of one of your assemblies and falsely claim it came from you, either by accident or intentionally.
  • Provide identity on reference. When resolving a reference to an assembly, strong names are used to guarantee the assembly that is loaded came from the expected publisher.

Strong names are implemented using standard public key cryptography. In general, the process works as follows: The author of an assembly generates a key pair (or uses an existing one), signs the file containing the manifest with the private key, and makes the public key available to callers. When references are made to the assembly, the caller records the public key corresponding to the private key used to generate the strong name. Figure 5 outlines how this process works at development time, including how keys are stored in the metadata and how the signature is generated.

The scenario is an assembly called "Main," which references an assembly called "MyLib." MyLib has a shared name. The important steps are described as follows.

Leave your comment.
Name
Email
Comments
Tell Us4776+5 =

Reduce your Dialy IT Cost, Consult with us
Stay healthy in recession

Advertisement
Sponsored by

Privacy Policy ©2009 ETG Consultancy, All Rights Reserved Terms & Conditions
Asp.net, Ado.net, .Net Remoting, .Net Webservice, SQL, XML, XSLT, WCF, WPF, WWF NHibernate, Ajax, Jquery, DHTML