Microsoft’s Visual Studio .NET has introduced many new concepts to the Visual Studio developer, including the Microsoft Intermediate Language (MSIL) with runtime compilation, garbage collection, Common Language Runtime (CLR), and, perhaps most misunderstood of all: namespaces and assemblies. To help you develop a better understanding of the .NET environment, this article will explore namespaces and assemblies and clarify the relationship between them.
At first glance, it appears as if namespaces represent little more than the C++ include directive or the addition of a VB module to a project. But the concept of namespaces and assemblies with the C# using directive and the VB Imports statement in Visual Studio .NET extends beyond the inclusion of predefined header files. They represent a method of interacting with external code libraries that may be new to the Microsoft developer.
Put simply, a namespace is just a grouping of related classes. It's a method of putting classes inside a container so that they can be clearly distinguished from other classes with the same name. Programmers skilled in the Java language will recognize namespaces as packages. A namespace is a logical grouping rather than a physical grouping. The physical grouping is accomplished by an assembly, which equates most directly to a dynamic link library (DLL), COM object, or OCX module.
The .NET CLR consists of multiple namespaces, which are spread across many assemblies. For example, ADO.NET is the set of classes located in the System.Data namespace, and ASP.NET is the set of classes located in the System.Web namespace.
Figure A shows how classes are divided up in the namespaces that compose the .NET CLR. Each block represents a separate namespace. In the CLR, the classes and structures contained in each of the namespaces represent a common theme of development responsibility. Further, the namespace system can be hierarchical, allowing for compartmentalization of functionality inside of a parent namespace. For example, the System namespace is the root for all other namespaces.
.NET CLR namespaces
It is important to understand that a namespace does not always equate to a functional library, such as in a traditional DLL, COM object, or OCX. In the .NET environment, namespaces represent the logical organization of code but not necessarily the physical location of the code.
In Visual Studio .NET, code is physically organized and structured in assemblies. An assembly is almost identical to a DLL, although one assembly consists of one or more DLL or EXEs. In fact, you will have a hard time finding references to the term DLL—it seems that Microsoft is keen to put the term into the annals of computer science history. Those with Java skills will recognize the assembly as a Jar file.
An assembly is a binary file that contains .NET executable code complied into MSIL. The relationship that exists between assemblies and namespaces can be rather confusing, since one assembly can contain one or more namespaces, and one namespace can be contained by one or more assemblies. Each assembly can be configured with a root namespace. If the root namespace value is left blank, the root namespace value defaults to the assembly name. You can set the root namespace through the project properties dialog box, as shown in Figure B.
Setting the root namespace
Assemblies provide many benefits over traditional DLL, OCX, or COM files. The following are just some of the advantages offered by the assembly design:
- Assemblies form .NET’s security boundary, which, with the assistance of the computer's security policy, can specify what actions can be performed.
- Assemblies introduce a cleaner method of object versioning than that presented by COM. The assembly naming and versioning system allows multiple objects to share the same name while still allowing an application to identify the correct object without the necessity of resorting to GUIDS.
- Assemblies provide for side-by-side (SxS) execution. With SxS execution, two applications (or the same application, for that matter) can instantiate two versions of the same object.
- While standard assemblies can be registered and placed in the global assembly cache, an assembly does not have to be registered to be useful. Unlike COM objects, which required the presence of entries in the NT/9X registry, the presence of an assembly in your application's directory is sufficient for it to be recognized by your application. This permits the development of simple applications that can be executed without an install process. This could mark the end of DLL hell and result in the return to the era of xCopy deployments. All you crackers will be pirating software for years to come!
Suppose you have a class called Manager residing in the Employee namespace, which resides in the Company.dll assembly. To use the class, you must first reference the assembly using the References section of the Solution Explorer. For Java programmers, this is analogous to placing the Jar file in the class path. This tells the project where to find the physical file. Once a reference is in place, you can use the imports Employee (VB) or using Employee (C#) directive to make use of the namespace. Imports can be done on a file basis or on a project basis. You should use the latter when you will use the namespace in a majority of the files in your project. For example, it is likely that you will use System.data in many of your files, so a project-level import for this namespace would be appropriate. Again, use the project properties dialog box to configure project level imports.
Although the relationship between namespaces and assemblies may be difficult to grasp at first, you must remember only that namespaces represent the logical view of your object model, and assemblies represent the physical deployment. Namespaces provide a hierarchical response to the difficulties of object identification and location. They remove many of the ambiguities found with other forms of object referencing and simplify library design by allowing related objects to reside together.
Through the use of assembly management, you can easily control versioning, security, and other aspects of library deployment that traditionally had to be performed by hand. Furthermore, the SxS assembly version enables hot swapping of loaded modules, not to mention simplified deployment. Welcome back xCopy, we’ve missed you. With all the advantages that the assembly/namespace pair offers, you may find yourself wondering how you ever got along without them.