Assembly in .NET: Part 1



An assembly in the .Net world is nothing but a DLL or an exe. It is a basic building block of any .Net application.

An Assembly contains metadata and manifest information. The reason for the emergence of assembly concept was to overcome the common "DLL Hell" problem in COM. The assembly contains all the code, resources, metadata and even version information. Metadata contains the details of every "type" inside the assembly. In addition to metadata, assemblies also have a special file called Manifest. It contains information about the current version of the assembly, culture information, public key token if available and other related information.

Assembly overcomes the famous DLL Hell problem. Previously, we were forced to have one version of DLL installed or rather registered on the system. The drawback was that if the same DLL is used in two components, fixing problems in one component would lead to causing problems on the other as the same DLL was used in both components. Now, with DLL we can have multiple versions of the same DLL . Also, we do not use registry anymore. If any assembly needs to be shared it is through Global Assembly Cache (GAC) and it can hold multiple versions of the same DLL.

There is a tool called ildasm which can used to view the assembly information. There is also a .Net reflector which can be used to dig into assembly details.

Functions of an assembly :

  1. It contains code that the common language runtime executes. It is a managed environment.
  2. It forms a security boundary. An assembly is the unit at which permissions are requested and granted
  3. It is the unit at which side-by-side execution is supported.
  4. It forms a deployment unit. When an application starts, only the assemblies that the application initially calls must be present. Other assemblies, such as localization resources or assemblies containing utility classes, can be retrieved on demand.
  5. It forms a version boundary. The assembly is the smallest versionable unit in the common language runtime; all types and resources in the same assembly are versioned as a unit.

There are in all 3 different types of assemblies :
  1. Private Assembly
  2. Shared or Strong named assembly
  3. Satellite assembly

This article focuses only on private assembly and few other assembly concepts. Private assembly is a managed standalone executable or a class library file.
  • Creating a simple assembly and referencing other assembly to it
  • Assembly probing

Note :: I have used Activator.CreateInstance to create an instance of a class within the assembly. You can also directly use Assembly.Load(<assemblyname>) and then create an instance of the assembly type.

1. Creating a simple assembly and referencing other assembly to it

I have a created an assembly called "AssemblyHost" and added reference to "Test" assembly. I am calling method "Add" defined within Test assembly's class.

Test Assembly

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
namespace Test
{
    public class MyClass
    {
        public static int Add(int i,int j)
        {
            return (i + j);
        }
    }
}


AssemblyHost assembly

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Test;

namespace
 AssemblyHost
{
    class Program
    {
        static void Main(string[] args)
        {
            int j = MyClass.Add(5, 7);
            Console.WriteLine(j.ToString());
            Console.ReadLine();
        }
    }
}

1.gif

Output

2.gif

2. Assembly Probing - .Net runtime searches for the assembly in the following path :
  • Look for the dll or exe under the Application directory (generally bin folder) or AppBase - Example shown above works in this fashion
  • Look for the assembly folder under the Application directory (generally bin/<assemblyname>) and try to find dll or exe .
  • Private probing using configuration file where you can define probe path. The same can also be done using Dotnet configuration utility (mscorcfg.msc) which is available in older versions of Dotnet. Dotnet 4.0 does not have this.

   
Suppose I create one more project "Test1" as seen below :
3.gif

When I try to load the new assembly without referencing, I get an error. However, if copy and paste a folder "Test1" under my application directory (bin/Debug) and copy the dll... works

Application Directory - AssemblyHost/bin/Debug

Folder Path - AssemblyHost/bin/Debug/Test

Dll Path - Folder Path/Test.dll

4.gif
  • Look for probing path defined under configuration file

I have to define my application config file as seen below to search for dll or exes to be loaded into my running assembly. The below configuration searches within MyLib folder inside my Application Directory and searches for all dlls.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
 
  
    <runtime>
      <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
        <probing privatePath="MyLib"/>
      </assemblyBinding>
    </runtime>
  
 
</configuration>

5.gif

Refer to the sample code for more details.
  • GAC (Global Assembly Cache)

If the private probing fails, then the assembly is searched from within GAC. I will cover GAC in the next part of this article.

Till then happy reading.