AspAlliance.com LogoASPAlliance: Articles, reviews, and samples for .NET Developers
URL:
http://aspalliance.com/articleViewer.aspx?aId=1238&pId=-1
Creating an Assembly Programmatically
page
by Uday Denduluri
Feedback
Average Rating: This article has not yet been rated.
Views (Total / Last 10 Days): 35356/ 52

Introduction

An assembly is a basic building block for any application in the .NET Framework. It is a fundamental unit of deployment, version control, reuse, activation scoping, and security permissions. An assembly is a collection of types and resources that are built to work together and form a logical unit of functionality. An assembly provides the Common Language Runtime (CLR) with the information it needs to be aware of type implementations. During runtime, a type does not exist outside the context of an assembly.

Creating an Assembly programmatically is one of the commonly unexplored features available to programmers. In some scenarios this may be a very useful feature. We can also create an assembly and add resources to it. In this article we focus on creating an assembly with a class and methods. Later on we will view reflection. We can also use ILDASM for viewing the contents of the assembly. Before we actually go about creating an assembly we need to understand what the contents of the assembly are.

The contents of an assembly are

·         CIL – Common Intermediate Language (formerly MSIL - Microsoft Intermediate Language)

·         Assembly Manifest – The Assembly Manifest has the information like Name, Version number, Culture, Strong Name information, etc.

·         Type Metadata

·         Resources

Assembly creation

The code shown in Listing 1 is to create an assembly programmatically. The code written is written in the C# language. The purpose of the code is to create an assembly with a class added to it. We also add a method to the class and finally save the dynamic assembly to the local system.

Listing 1

AppDomain currentDomain = Thread.GetDomain();
AssemblyName myAssemblyName = new AssemblyName();
myAssemblyName.Name = "Test";
myAssemblyName.Version = new Version(1, 0, 0, 0);
AssemblyBuilder builder = currentDomain.DefineDynamicAssembly(myAssemblyName,
 AssemblyBuilderAccess.RunAndSave);
ModuleBuilder ObjModuleBuilder = builder.DefineDynamicModule("MyModule");
ObjModuleBuilder.DefineType("ClassName",
 TypeAttributes.Class).DefineMethod("MethodName",
 MethodAttributes.Public, CallingConventions.Standard);
builder.Save("MyAssembly.dll");

The AssemblyBuilder class is completely responsible for the creation of an assembly. An instance of the AssemblyBuilder class can be created by the current AppDomain. The steps for creating the assembly are listed below.

Step 1: Get the current application domain from the current thread.

Step 2: Create an object of the type AssemblyBuilder from the current application domain.

Step 3: Create the module builder object from the AssemblyBuilder.

Step 4: Create the different types, methods, etc. and add them to the Module Builder.

Step 5: Save the builder to the local system.

The complete description of each and every class used is illustrated in the next section.

Classes Used for Creating an Assembly

Let us now understand the types used for creating the Assembly. Let us understand each one of them in detail.

Type Name

Description

AssemblyBuilder

Defines and represents a dynamic assembly. A dynamic assembly is an assembly that is created using the Reflection Emit APIs. The dynamic modules in the assembly are saved when the dynamic assembly is saved using the Save method.

An AssemblyBuilder object is created by the DefineDynamicAssembly method of the AppDomain Class.

ModuleBuilder

Defines and represents a module. A ModuleBuilder instance can be created by calling DefineDynamicModule method of the AssemblyBuilder class.

 

TypeBuilder

Defines and creates new instances of classes during runtime. This can be created by the CreateType Method of the ModuleBuilder class

AppDomain

Represents an application domain, which is an isolated environment where applications execute. We can create this by using the CreateDomain method, but we need the current AppDomain instance. Hence, we take it from the current thread in which the application is running.

AssemblyName

Describes an assembly's unique identity in full. The AssemblyName object contains information about an assembly, which can be used to bind to that assembly. An assembly's identity consists of the simple name, version number, cryptographic key pair, and supported culture. We need to use this instance to give the name of the assembly.

AssemblyBuilderAccess

Defines the access modes for a dynamic assembly. This is an enumeration. The enumeration values are as follows ReflectionOnly – The dynamic assembly is loaded into the reflection-only context and cannot be executed. 

Run - The dynamic assembly can be executed but not saved. 

RunAndSave – The dynamic assembly can be executed and saved. 

Save – The dynamic assembly can be saved but not executed.

 

Overview of ILDASM

Intermediate Language Disassembler (ILDASM) is a utility which loads the assembly and shows the contents of the Assembly. Let us create an assembly and view the contents through ILDASM. This will help us to understand how ILDASM displays the contents of the assembly.

We have created a namespace with the name Namespace1 and a class with class1. The class has a single method, Method1, which is a void method. We can view the created assembly using this tool.

Figure 1

Difference between Assembly and Satellite Assembly

The Common Language Runtime (CLR) differentiates an assembly from a satellite assembly by an attribute called the "AssemblyCultureAttribute". A regular assembly contains code and the neutral culture's resources. A satellite assembly contains only resources for a particular culture, as in [assembly: AssemblyCultureAttribute ("en-US")]. Putting this attribute on an assembly and using something other than the empty string ("") for the culture name will make this assembly a satellite assembly rather than a regular assembly that contains executable code. Labeling a traditional code library with this attribute will break it, because no other code will be able to find the library's entry points at runtime. We have a culture attribute in the Global Assembly Cache (GAC). If we open it and see, we find that it does not have a value for a normal assembly and has the culture name shown for the satellite assembly. This can be stated as the vital difference between an assembly and a satellite assembly.

Conclusion

Assemblies are a fundamental part of programming with the .NET Framework. An assembly performs the following functions; contains code that the common language runtime executes, forms a security boundary, acts as the unit at which permissions are requested and granted, forms a type boundary, forms a reference scope boundary, forms a version boundary, and forms a deployment unit. Creating an assembly can be done programmatically, and that creation of an assembly is done with the help of various classes like the AssemblyBuilder, ModuleBuilder, AppDomain, AssemblyName, etc.

The compiler differentiates an assembly from a satellite assembly by an attribute called AssemblyCultureAttribute. This attribute will be filled with the appropriate value to identify the assembly as a normal assembly or a satellite assembly.

References


©Copyright 1998-2024 ASPAlliance.com  |  Page Processed at 2024-03-18 10:01:21 PM  AspAlliance Recent Articles RSS Feed
About ASPAlliance | Newsgroups | Advertise | Authors | Email Lists | Feedback | Link To Us | Privacy | Search