Assemblies in .NET

 Assemblies  are the fundamental building blocks of a .NET Framework application. They contain the types and resources that make up an application and describe those contained types to the common language runtime.  Assemblies  enable code reuse, version control, security, and deployment.

Put simply, an  assembly  is a project that compiles to an EXE or a DLL file. Although .NET EXE and DLL files resemble their predecessors externally, the internal structure of an  assembly  is quite different from that of an EXE or DLL created with earlier development tools. An  assembly  consists of four internal parts:

The  assembly  manifest, or metadata. This contains information about the  assembly  that the common language runtime uses to obtain information about the  assembly . The type metadata, which exposes information about the types contained within the  assembly .

The intermediate language code for your  assembly .

Resource files, which are non-executable bits of data, such as strings or images for a specific culture. The  assembly  manifest contains the metadata that describes the  assembly  to the common language runtime. The common language runtime then uses the information in the  assembly  manifest to make decisions about the  assembly’s  execution. An  assembly  manifest contains the following information: Identity.

It contains the name and version number of the  assembly , and can contain optional information such as locale and signature information. Types and resources. It contains a list of all the types that will be exposed to the common language runtime as well as information about how those types can be accessed. Files: It contains a list of all files in the  assembly  as well as dependency information for those files. Security permissions

The manifest describes the security permissions required by the  assembly . If the permissions required conflict with the local security policy, the  assembly  will fail to execute. For the most part, the developer does not have to be concerned with the contents of the  assembly  manifest. It is compiled and presented to the common language runtime automatically. The developer does, however, need to explicitly set the metadata that describes the identity of the  assembly . The identity of the  assembly  is contained in the AssemblyInfo.vb or .cs file for your project. You can set identity information for your  assembly  by right-clicking the AssemblyInfo icon and choosing View Code from the drop-down menu. The code window will open to the AssemblyInfo code page, which contains default null values for several  assembly  identity attributes. The following code example shows an excerpt from the AssemblyInfo file.

Creating Class Library  Assemblies 

You will frequently want to create class library  assemblies . These represent sets of types that can be referenced and used in other  assemblies . For example, you might have a custom control that you want to use in several applications or a component that exposes higher math functions. Such an  assembly  is not executable itself, but rather must be referenced by an executable application to be used. You can create class library  assemblies  and control library  assemblies  by using the templates provided by Microsoft Visual Studio .NET.

The class library template is designed to help you create an  assembly  of types that can be exposed to other applications, and the Microsoft Windows control library template is provided to assist you in building  assemblies  of custom controls.

Creating Resource Files

The .NET Framework includes a sample application called ResEditor that can be used for creating text and image resource files. The ResEditor application is not integrated with Visual Studio .NET-it must be run separately. In fact, it is supplied as source code files and must be compiled before it can be used.

The ResEditor source files are located in the FrameworkSDKSamplesTutorialsresourcesandlocalizationreseditor folder, which is in the folder that Visual Studio .NET is installed in. You can build the application using either the batch file supplied in that folder or by adding the source files to an empty Visual Studio project, configuring, and then building them.

Embedding Resources

Once you have created resource files, you can embed them in your  assembly . This allows you to package resources into the same  assembly  as the code files, thus increasing the portability of your code and reducing its dependence on additional files. To embed an externally created resource into your  assembly , all you have to do is add the file to your project. When the project is built, the resource file will be compiled into the  assembly .

Creating Resource  Assemblies 

You can create  assemblies  that only contain resources. You might find this useful in situations where you expect to have to update the data contained in resource files, but do not want to have to recompile your application to update it.

Creating Satellite  Assemblies 

When creating international applications, you might want to provide different sets of resources for different cultures. Satellite  assemblies  allow different sets of resources to automatically be loaded based on the CurrentUICulture setting of the thread. You learned how to automatically generate applications for localization in Chapter 8. In this section, you will learn how to create additional satellite  assemblies  and incorporate them into your application.

Visual Studio .NET allows you to effortlessly create satellite  assemblies . All you need to do to create a satellite  assembly  is to incorporate alternate sets of resource files that are appropriately named into your application. Visual Studio .NET does the rest upon compilation.

To be incorporated into a satellite  assembly , your resource file must follow a specific naming scheme based on the culture it is designed for. The name of a resource file for a specific culture is the same as the name of the resource file for the invariant culture, and the culture code is inserted between the base name and the extension. Thus, if we had a resource file named MyResources.resx, a resource file containing alternate resources for neutral German UIs would be named MyResources.de.resx. And a version of the file containing German resources specific for Luxembourg would be named MyResources.de-LU.resx.

Once these alternate versions of the file are added to your solution, they will automatically be compiled by Visual Studio .NET into satellite  assemblies , and a directory structure for them will be created. At run time, the culture-specific resources contained in these files will automatically be located by the common language runtime.

Retrieving Resources at Run Time

At run time, you can use the ResourceManager class to retrieve embedded resources. A ResourceManager, as the name implies, manages access and retrieval of resources embedded in  assemblies . Each instance of a ResourceManager is associated with an  assembly  that contains resources.

You can create a ResourceManager by specifying two parameters: the base name of the embedded resource file and the  assembly  in which that file is found. The new ResourceManager will be dedicated to the embedded resource file that you specify. The base name of the file is the name of the namespace that contains the file and the file without any extensions.

The  assembly  parameter refers to the  assembly  that the resource file is located in. If the  assembly  that contains the resources is the same  assembly  that contains the object that is creating the ResourceManager, you can get a reference to the  assembly  from the type object of your object.

Understanding Private and Shared  Assemblies 

Most of the  assemblies  you create will be private  assemblies . Private  assemblies  are the most trouble free for developers and are the kind of  assembly  created by default. A private  assembly  is an  assembly  that can be used by only one application. It is an integral part of the application, is packaged with the application, and is only available to that application. Because private  assemblies  are used by one application only, they do not have versioning or identity issues. Up to this point, you have only created private  assemblies .

When you add a reference to a private  assembly  to your project, Visual Studio .NET creates a copy of the DLL containing that  assembly  and writes it to your project folder. Thus, multiple projects can reference the same DLL and use the types it contains, but each project has its own copy of the DLL and therefore has its own private  assembly .

Only one copy of shared  assemblies , on the other hand, is present per machine. Multiple applications can reference and use a shared  assembly . You can share an  assembly  by installing it to the Global  Assembly  Cache. There are several reasons why you might want to install your  assembly  to the Global  Assembly  Cache. For example:

Shared location. If multiple applications need to access the same copy of an  assembly , it should be shared.

Security. The Global  Assembly  Cache is located in the C:WINNT (Microsoft Windows 2000) or WINDOWS (Microsoft Windows XP) folder, which is given the highest level of security by default.

Side-by-side versioning. You can install multiple versions of the same  assembly  to the Global  Assembly  Cache, and applications can locate and use the appropriate version.

For the most part, however,  assemblies  that you create should be private. You should only share an  assembly  when there is a valid reason to do so. Sharing an  assembly  and installing it to the Global  Assembly  Cache requires that your  assembly  be signed with a strong name.