Private assembly vs. Global assembly

In this article, I would explain how to create a class library and use it.  We start understanding what is an assembly, then
we understand how to create an assembly and use it. As by default assemblies are private, we also understand what is the difference between private and global assembly and how to convert a private assembly to global assembly.

What is an assembly in .NET?

An assembly is a fundamental unit of any .NET application. It contains the code that is executed by CLR (common language runtime). I would like to limit the details to what is required to create and use an assembly. For more information about all nitty gritties of an assembly, please refer to MSDN documentation.

However, it is important to know a few details about assemblies before we delve into creating and using it.

Structure of an Assembly

The following is the content of an assembly. Each assembly contains first three parts. Fourth part may not be present in all assemblies. It is used primarily for localization - using resources according to the country or region.

Assembly Metadata or Manifest

This contains information about the assembly. Remember, assemblies in .NET are self-describing. They contain all the information that .NET needs to use them. Assembly metadata contains the following details of an assembly:

Type metadata

This section of an assembly contains information about all classes, structure etc. created in the assembly.

MSIL Code

MSIL code of the assembly is placed in third part of the assembly. This MSIL is converted to native code by CLR at runtime.

Resource

This section contains messages and pictures used by assembly.

How to create an assembly in C#

The following are the steps to create a private assembly (by default all assemblies are private) using Visual C# 2005 Express Edition.
  1. Select File->New Project
  2. From Templates, select Class Library
  3. Enter name CounterLibrary
  4. A class library is created using a single class Class1
  5. Rename class to Counter and add the following code.
    namespace CounterLibrary
    {
        public class Counter
        {
            protected int v = 0;
            public Counter(int v)
            {
                this.v = v;
            }
            public int Value
            {
                get
                {
                    return v;
                }
            }
        }
    }
    
  6. Save project using File->Save All. When prompted to enter location for project, select the folder where you want to save your project. I use c:\csharp. Do not select checkbox for Create directory for solution
  7. Build (not run) the project using Build->Build Solution
After the above process, we get CounterLibrary.dll assembly placed in c:\csharp\counterlibrary\bin\release directory.

The next step is to use this assembly in a console application. As a matter of fact, once a source program is converted to MSIL, it can be used anywhere in .NET, irrespective of language and type of application.

Using a private assembly in a console application developed in C#

Now, let us use the class library created in C# in a console application. Though I am using a console application in C#, you can use any language supported by .NET. 
  1. Start Visual C# 2005 Express Edition
  2. Create a new console application using File -> New Project
  3. From template select Console Application as type of project
  4. Give name UseCounter for application.
    A new application is created with a single class with Main() method.
  5. Go to Solution Explorer and select project
  6. Right click on it and select Add References from the context menu.
  7. From dialog box, select Browse tab and select c:\csharp\counterlibrary\bin\release\counterlibrary.dll
  8. Solution explorer displays counterlibrary as one of the references under references node in solution explorer
  9. Add the following code in Main() method of Program.cs
    using System;
    namespace UseCounter
    {
        class Program
        {
            static void Main(string[] args)
            {
                counterlibrary.Counter c = new counterlibrary.Counter(100);
                c.Inc();
                Console.WriteLine(c.Value);
            }
        }
    }
    
As you do the above, you can notice that a copy of counterlibrary.dll is copied into BIN directory of UseCounter application. This is the case with any private library. Whenever an application makes a reference to it, a copy of private assembly is copied into it's bin directory.

If you do not see .DLL file that is copied to BIN directory of console application (UseCounter), close the application and reopen it.

Making a private assembly a global assembly

A global assembly is a public assembly that is shared by multiple applications. Unlike private assembly, a global assembly is not copied to bin directory of each application that references it. Global assembly instead is placed in GAC (Global Assembly Cache) and it can be referenced anywhere within the system. So only one copy is stored, but many applications can use that single copy.

In order to convert a private assembly to global assembly, we have to take the following steps.

Creating a strong name

Any assembly that is to be placed in GAC, must have a strong name. Strong name is a combination of public key and private key. The relationship between public and private keys are such, given one you cannot get the other, but any data that is encrypted with private key can be decrypted only with the corresponding public key.

Take the following steps to invoke SN (Strong Name) tool to create strong name.

  1. Go to command prompt using Microsoft .NET Framework SDK v2.0 -> SDK Command prompt
  2. Go to c:\csharp\counterlibrary folder and enter the following command.
  3. sn -k srikanth.key
    
    The above command writes private and public key pair into srikanth.key file.

Associate strong name with assembly

Once private and public keys are generated using SN tool, use the following procedure to sign counterlibrary with the key file.
  1. Open counterlibrary project.
  2. Select project properties using Project -> counterlibrary properties
  3. Select Signing tab in project properties window
  4. Check Sign the assembly check box
  5. Select srikanth.key file using Choose a strong name key file combo box
  6. Close properties window
  7. Build the solution again using Build->Build Solution
Now, counterlibrary.dll is associated with a public key and also digitally signed with private key. This ensures no one can modify this assembly as any change to assembly should re-sign the assembly with private key of the user who created it first. This protects the assembly from getting tampered with by others. A global assembly needs this projection as it is placed in common place.

You can verify whether the assembly is associated with public key using ILDASM (IL Disassembler) program provided by .NET Framework.

Place assembly in GAC

In order to make an assembly a global assembly, the assembly must be associated with a strong name and then placed in Global Assembly Cache (GAC).

GAC is a folder with name Assembly in windows folder of your system. So, place counterlibrary.dll in GAC using GACUTIL tool as follows.

c:\csharp\counterlibrary\bin\Release>gacutil -i counterlibrary.dll

After you install global assembly into GAC, you can see counterlibrary.dll in windows/assembly folder.

Once, you place an assembly in GAC, any reference to the assembly will not create a copy of the assembly in BIN directory of the application. Instead all application that reference the assembly use the same copy that is placed in GAC.

Keep Learning,
P.Srikanth.

If you have anything to say about this article, please use Feedback Form to provide feedback.