Assembly Structure


An assembly consists of assembly metadata describing the complete assembly, type metadata describing the exported types and methods, MSIL code, and resources. All these parts can be inside of one file or spread across several files.

In this example (see Figure 16-2), the assembly metadata, type metadata, MSIL code, and resources are all in one file - Component.dll. The assembly consists of a single file.

image from book
Figure 16-2

The second example shows a single assembly spread across three files (see Figure 16-3). Component.dll has assembly metadata, type metadata, and MSIL code, but no resources. The assembly uses a picture from picture.jpeg that is not embedded inside Component.dll, but is referenced from within the assembly metadata. The assembly metadata also references a module called util.netmodule, which itself includes only type metadata and MSIL code for a class. A module has no assembly metadata; thus the module itself has no version information; it also cannot be installed separately. All three files in this example make up a single assembly; the assembly is the installation unit. It would also be possible to put the manifest in a different file.

image from book
Figure 16-3

Assembly Manifests

An important part of an assembly is a manifest, which is part of the metadata. It describes the assembly with all the information that’s needed to reference it and lists all its dependencies. The parts of the manifest are as follows:

  • Identity -  (name, version, culture, and public key)

  • A list of files -  Files belonging to this assembly. A single assembly must have at least one file but may contain a number of files.

  • A list of referenced assemblies -  All assemblies used from the assembly are documented inside the manifest. This reference information includes the version number and the public key, which is used to uniquely identify assemblies. The public key is discussed later in this chapter.

  • A set of permission requests -  These are the permissions needed to run this assembly. You can find more information about permissions in Chapter 19, “.NET Security.”

  • Exported types -  These are included if they are defined within a module and the module is referenced from the assembly; otherwise, they are not part of the manifest. A module is a unit of reuse. The type description is stored as metadata inside the assembly. You can get the structures and classes with the properties and methods from the metadata. This replaces the type library that was used with COM to describe the types. For the use of COM clients it’s easy to generate a type library out of the manifest. The reflection mechanism uses the information about the exported types for late binding to classes. See Chapter 12, “Reflection,” for more information about reflection.

Namespaces, Assemblies, and Components

You might be a little bit confused by the meanings of namespaces, types, assemblies, and components. How does a namespace fit into the assembly concept? The namespace is completely independent of an assembly. You can have different namespaces in a single assembly, but the same namespace can be spread across assemblies. The namespace is just an extension of the type name - it belongs to the name of the type. Thus, the real name of the class Demo you used before is Wrox.ProCSharp.Assemblies.AppDomains.Demo.

The diagram in Figure 16-4 should help to make this concept clearer. It shows three assemblies, which you build later in this chapter - an assembly written with C++/CLI, one with Visual Basic, and one with C#. All these assemblies have classes in the same namespace: Wrox.ProCSharp.Assemblies .CrossLanguage. The assembly HelloCSharp, in addition, has a Math class that’s in the namespace Wrox.Utils.

image from book
Figure 16-4

Private and Shared Assemblies

Assemblies can be shared or private. A private assembly is found either in the same directory as the application, or within one of its subdirectories. With a private assembly, it’s not necessary to think about naming conflicts with other classes or versioning problems. The assemblies that are referenced during the build process are copied to the application directory. Private assemblies are the normal way to build assemblies, especially when applications and components are built within the same company.

When using shared assemblies, you have to be aware of some rules. The assembly must be unique and therefore must also have a unique name called a strong name. Part of the strong name is a mandatory version number. Shared assemblies will mostly be used when a vendor, different from that of the application, builds the component, or when a large application is split into subprojects.

Viewing Assemblies

Assemblies can be viewed using the command-line utility ildasm, the MSIL disassembler. You can open an assembly by starting ildasm from the command line with the assembly as an argument or by selecting the File image from book Open menu.

Figure 16-5 shows ildasm opening the example that you build a little later in the chapter, HelloCSharp.exe. ildasm shows the manifest and the HelloCSharp type in the Wrox.ProCSharp .Assemblies.CrossLanguage namespace. When you open the manifest, you can see the version number and the assembly attributes, as well as the referenced assemblies and their versions. You can see the MSIL code by opening the methods of the class.

image from book
Figure 16-5

ildasm symbols

The following table lists the symbols used with ildasm.

Open table as spreadsheet

Symbol

Description

image from book

Represents a namespace.

image from book

Represents a reference type, a class. Similar symbols are used by value types (structs) that have a light color, delegates that are real classes with the MSIL code, interfaces that have an “I” in the graphic, and enumerations with an “E.”

image from book

Represents a method and get and set accessors of a property; an “S” in the graphic means that this method is static.

image from book

Represents a field.

image from book

Represents an event.

image from book

Represents a property.

image from book

This means that more information is available (for example, manifest information or information about a class declaration).

Important 

In addition to using ildasm, the .NET Reflector is another great tool to use to analyze assemblies. The .NET Reflector allows type and member search, and call and callee graphs, and decompiles IL code to C#, C++, or Visual Basic. You can download this tool from www.aisto.com/roeder/dotnet.

Building Assemblies

Now that you know what assemblies are, it is time to build some. Of course, you have already built assemblies in previous chapters, because a .NET executable counts as an assembly. This section looks at special options for assemblies.

Creating Modules and Assemblies

All C# project types in Visual Studio create an assembly. Whether you choose a DLL or EXE project type, an assembly is always created. With the command-line C# compiler csc, it’s also possible to create modules. A module is a DLL without assembly attributes (so it’s not an assembly, but it can be added to assemblies at a later time). The command

 csc /target:module hello.cs 

creates a module hello.netmodule. You can view this module using ildasm.

A module also has a manifest, but there is no .assembly entry inside the manifest (except for the external assemblies that are referenced) because a module has no assembly attributes. It’s not possible to configure versions or permissions with modules; that can only be done at the assembly scope. You can find references to assemblies in the manifest of the module. With the /addmodule option of csc, it’s possible to add modules to existing assemblies.

To compare modules to assemblies, create a simple class A and compile it by using the following command:

 csc /target:module A.cs 

The compiler generates the file A.netmodule, which doesn’t include assembly information (as you can see using ildasm to look at the manifest information). The manifest of the module shows the referenced assembly mscorlib and the .module entry in Figure 16-6.

image from book
Figure 16-6

Next, create an assembly B, which includes the module A.netmodule. It’s not necessary to have a source file to generate this assembly. The command to build the assembly is:

 csc /target:library /addmodule:A.netmodule /out:B.dll 

Looking at the assembly using ildasm, you can only find a manifest. In the manifest, the assembly mscorlib is referenced. Next, you see the assembly section with a hash algorithm and the version. The number of the algorithm defines the type of the algorithm that was used to create the hash code of the assembly. When creating an assembly programmatically it is possible to select the algorithm. Part of the manifest is a list of all modules belonging to the assembly. In Figure 16-7 you see .module A.netmodule, which belongs to the assembly. Classes exported from modules are part of the assembly manifest; classes exported from the assembly itself are not.

image from book
Figure 16-7

What’s the purpose of modules? Modules can be used for faster startup of assemblies because not all types are inside a single file. The modules are loaded only when needed. Another reason to use modules is if you want to create an assembly with more than one programming language. One module could be written using Visual Basic, another module could be written using C#, and these two modules could be included in a single assembly.

Creating Assemblies Using Visual Studio

As already mentioned, all project types in Visual Studio create assemblies. With Visual Studio 2005, there’s no support for creating modules directly.

When creating a Visual Studio project, the source file AssemblyInfo.cs is generated automatically. You can find this file below Properties in Solution Explorer. You can use the normal Source Code editor to configure the assembly attributes in this file. This is the file generated from the wizard:

  using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // // General Information about an assembly is controlled through the // following set of attributes. Change these attribute values to modify // the information associated with an assembly. // [assembly: AssemblyTitle("DomainTest")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("DomainTest")] [assembly: AssemblyCopyright("Copyright @ Wrox Press 2007")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // Setting ComVisible to false makes the types in this assembly not visible // to COM components.  If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed // to COM [assembly: Guid("")] // // Version information for an assembly consists of the following four // values: // //      Major Version //      Minor Version //      Build Number //      Revision // [assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.0.0.0")] 

This file is used for configuration of the assembly manifest. The compiler reads the assembly attributes to inject the specific information into the manifest.

[assembly] and [module] are assembly-level attributes. Assembly-level attributes are, in contrast to the other attributes, not attached to a specific language element. The arguments that can be used for the assembly attribute are classes of the namespaces System.Reflection, System.Runtime.CompilerServices, and System.Runtime.InteropServices.

Tip 

You can read more about attributes and how to create and use custom attributes in Chapter 12, “Reflection.”

The following table contains a list of assembly attributes defined within the System.Reflection namespace.

Open table as spreadsheet

Assembly Attribute

Description

AssemblyCompany

Specifies the company name.

AssemblyConfiguration

Specifies build information such as retail or debugging information.

AssemblyCopyright and AssemblyTrademark

Hold the copyright and trademark information.

AssemblyDefaultAlias

Can be used if the assembly name is not easily readable (such as a GUID when the assembly name is created dynamically). With this attribute an alias name can be specified.

AssemblyDescription

Describes the assembly or the product. Looking at the properties of the executable file this value shows up as Comments.

AssemblyProduct

Specifies the name of the product where the assembly belongs.

AssemblyInformationalVersion

This attribute isn’t used for version checking when assemblies are referenced, it is for information only. It is very useful to specify the version of an application that uses multiple assemblies. Opening the properties of the executable you can see this value as the Product Version.

AssemblyTitle

Used to give the assembly a friendly name. The friendly name can include spaces. With the file properties you can see this value as Description.

Here’s an example of how these attributes might be configured:

 [assembly: AssemblyTitle("Professional C#")] [assembly: AssemblyDescription("Sample Application")] [assembly: AssemblyConfiguration("Retail version")] [assembly: AssemblyCompany("Wrox Press")] [assembly: AssemblyProduct("Wrox Professional Series")] [assembly: AssemblyCopyright("Copyright (C) Wrox Press 2007")] [assembly: AssemblyTrademark("Wrox is a registered trademark of " +       "John Wiley & Sons, Inc.")] [assembly: AssemblyCulture("")]

With Visual Studio 2005 you can configure these attributes with the project properties, Application settings, and Assembly Information, as you can see in Figure 16-8.

image from book
Figure 16-8

The following attributes correspond to classes in the System.Runtime.CompilerServices namespace:

  • AssemblyCulture tells about the culture of the assembly. Cultures are discussed in Chapter 20, “Localization.”

  • AssemblyVersion specifies the version number of the assembly. Versioning plays an important part in shared assemblies.

Tip 

Additional COM interoperability attributes within the System.Runtime.InteropServices namespace can be used to make .NET types visible to COM, to specify application IDs, for example. COM interoperability is the subject of Chapter 23, “COM Interoperability.”




Professional C# 2005 with .NET 3.0
Professional C# 2005 with .NET 3.0
ISBN: 470124725
EAN: N/A
Year: 2007
Pages: 427

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net