Modules and Assemblies
A module is an .exe or .dll file. An assembly is a set of one or more modules that together make up an application. If the application is fully contained in an .exe file, fine—that's a one-module assembly. If the .exe is always deployed with two .dll files and one thinks of all three files as comprising an inseparable unit, then the three modules together form an assembly, but none of them does so by itself. If the product is a class library that exists in a .dll file, then that single .dll file is an assembly. To put it in Microsoft's terms, the assembly is the unit of deployment in .NET.
An assembly is more than just an abstract way to think about sets of modules. When an assembly is deployed, one (and only one) of the modules in the assembly must contain the assembly manifest, which contains information about the assembly as a whole, including the list of modules contained in the assembly, the version of the assembly, its culture, etc. The command-line compiler and the Visual Studio .NET compiler create single-module assemblies by default. Multiple-module assemblies are not used in this book.
Assembly boundaries affect type resolution. When a source file is compiled, the compiler must resolve type names used in the file to the types' definitions. For types that are defined in the same source project, the compiler gets the definitions from the code it is compiling. For types that are defined elsewhere, the compiler must be told where to find the definitions.
This is done by referencing the assemblies that contain the compiled type definitions. When the command-line compiler is used, the /reference switch identifies assemblies containing types used in the project being compiled. An assembly has the same name as the module that contains the assembly manifest, except for the file extension. In some cases, however, an assembly is specified by giving the full name of the module that contains the assembly manifest. For example, to compile an application that uses the System.Drawing.Point class, you could use the following command line:
Global Assembly Cache (GAC)
By default, assemblies are not shared. When one assembly is dependent on another, the two assemblies are typically deployed into a single application directory. This makes it easy to install and remove an application. To install an application, simply create the application directory and copy the files into it. To delete the application, just delete the application directory. The Windows Registry is not used at all.
If an assembly must be shared among more than one program, either it can be copied into each appropriate application directory or it can be installed into the global assembly cache (GAC). The GAC is an area on disk (typically, it's the assembly subdirectory of the Windows directory) that holds assemblies to be shared among all applications.
All of the .NET Framework assemblies reside in the GAC. Placing an assembly into the GAC should be avoided if possible: it makes application installation and removal more difficult. This is because the Windows Installer or gacutil.exe must be used to manipulate the GAC—you can no longer simply copy or remove the application directory. Installing assemblies into the GAC is not covered in this book. For information, point your browser to http://msdn.microsoft.com and perform a search for "Deploying Shared Components."
Comparison of Assemblies, Modules, and Namespaces
It's easy to confuse the three concepts of namespace, module, and assembly. Here is a recap:
Namespace
A portion of a type name. Specifically, it is the portion that precedes the final period in a fully qualified type name.
Module
A file that contains executable code (.exe or .dll).
Assembly
A set of one or more modules that are deployed as a unit. The assembly name is the same as the name of the module that contains the assembly manifest, minus the filename extension.
Depending on how things are named, it can seem like these three terms are interchangeable. For example, System.Drawing.dll is the name of a module that is deployed as part of the .NET Framework.
Application Domains
Application domains are to the CLR what processes are to an operating system. It may be surprising to note that the CLR can run multiple .NET applications within a single process, without any contention or security difficulties. Because the CLR has complete control over loading and executing programs, and because of the presence of type information, the CLR guarantees that .NET applications cannot read or write each other's memory, even when running in the same process.
Because there is less performance overhead in switching between application domains than in switching between processes, this provides a performance gain. This is especially beneficial to web applications running in Internet Information Services (IIS), where scalability is an issue.
A module is an .exe or .dll file. An assembly is a set of one or more modules that together make up an application. If the application is fully contained in an .exe file, fine—that's a one-module assembly. If the .exe is always deployed with two .dll files and one thinks of all three files as comprising an inseparable unit, then the three modules together form an assembly, but none of them does so by itself. If the product is a class library that exists in a .dll file, then that single .dll file is an assembly. To put it in Microsoft's terms, the assembly is the unit of deployment in .NET.
An assembly is more than just an abstract way to think about sets of modules. When an assembly is deployed, one (and only one) of the modules in the assembly must contain the assembly manifest, which contains information about the assembly as a whole, including the list of modules contained in the assembly, the version of the assembly, its culture, etc. The command-line compiler and the Visual Studio .NET compiler create single-module assemblies by default. Multiple-module assemblies are not used in this book.
Assembly boundaries affect type resolution. When a source file is compiled, the compiler must resolve type names used in the file to the types' definitions. For types that are defined in the same source project, the compiler gets the definitions from the code it is compiling. For types that are defined elsewhere, the compiler must be told where to find the definitions.
This is done by referencing the assemblies that contain the compiled type definitions. When the command-line compiler is used, the /reference switch identifies assemblies containing types used in the project being compiled. An assembly has the same name as the module that contains the assembly manifest, except for the file extension. In some cases, however, an assembly is specified by giving the full name of the module that contains the assembly manifest. For example, to compile an application that uses the System.Drawing.Point class, you could use the following command line:
vbc MySource.vb /reference:System.Drawing.dll
The documentation for the command-line compiler states that the argument to the reference switch is an assembly. This is not quite accurate. The argument is the name of the module that contains the assembly manifest for an assembly.
If more than one assembly needs to be referenced, you can list them all in the same /reference switch, separated by commas, like this:
If more than one assembly needs to be referenced, you can list them all in the same /reference switch, separated by commas, like this:
vbc MySource.vb /reference:System.Drawing.dll,System.Windows.Forms.dll
When you're working within the Visual Studio .NET IDE, external assemblies are referenced by doing the following:
- In the Solution Explorer window, right-click on References, then click on Add Reference. The Add Reference dialog box appears,
- Scroll down to find the desired assembly.
- Double-click or highlight the assembly name, and press the Select button. The assembly
- name appears in the Selected Components frame of the dialog box.
- Select additional assemblies, or click OK.
Global Assembly Cache (GAC)
By default, assemblies are not shared. When one assembly is dependent on another, the two assemblies are typically deployed into a single application directory. This makes it easy to install and remove an application. To install an application, simply create the application directory and copy the files into it. To delete the application, just delete the application directory. The Windows Registry is not used at all.
If an assembly must be shared among more than one program, either it can be copied into each appropriate application directory or it can be installed into the global assembly cache (GAC). The GAC is an area on disk (typically, it's the assembly subdirectory of the Windows directory) that holds assemblies to be shared among all applications.
All of the .NET Framework assemblies reside in the GAC. Placing an assembly into the GAC should be avoided if possible: it makes application installation and removal more difficult. This is because the Windows Installer or gacutil.exe must be used to manipulate the GAC—you can no longer simply copy or remove the application directory. Installing assemblies into the GAC is not covered in this book. For information, point your browser to http://msdn.microsoft.com and perform a search for "Deploying Shared Components."
Comparison of Assemblies, Modules, and Namespaces
It's easy to confuse the three concepts of namespace, module, and assembly. Here is a recap:
Namespace
A portion of a type name. Specifically, it is the portion that precedes the final period in a fully qualified type name.
Module
A file that contains executable code (.exe or .dll).
Assembly
A set of one or more modules that are deployed as a unit. The assembly name is the same as the name of the module that contains the assembly manifest, minus the filename extension.
Depending on how things are named, it can seem like these three terms are interchangeable. For example, System.Drawing.dll is the name of a module that is deployed as part of the .NET Framework.
Application Domains
Application domains are to the CLR what processes are to an operating system. It may be surprising to note that the CLR can run multiple .NET applications within a single process, without any contention or security difficulties. Because the CLR has complete control over loading and executing programs, and because of the presence of type information, the CLR guarantees that .NET applications cannot read or write each other's memory, even when running in the same process.
Because there is less performance overhead in switching between application domains than in switching between processes, this provides a performance gain. This is especially beneficial to web applications running in Internet Information Services (IIS), where scalability is an issue.
No comments:
Post a Comment