Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Dynamic Loading of Assemblies at Runtime through .NET Reflection

0.00/5 (No votes)
8 Sep 2010 2  
Shows the ability of .NET to load assemblies at run time based on appropriate necessities by using the power of late binding and reflection

Objective

The objective of this paper is to show the ability of .NET to load assemblies at run time based on appropriate necessities by using the power of late binding and reflection.

Introduction

In a typical N-tier application, we have the:

  1. Presentation Layer – which forms the user interface to the application
  2. Application Layer – which handles the business logic
  3. The Data Access Layer – Interacts with the database

Usually, these three layers are completely isolated from each other and make calls through assembly references. The presentation layer can be totally separated from the business layer and be totally oblivious of its functioning and data type. It is only interested in the data that the business layer provides. Also, the business layer can cater to more than one presentation layers (web, Windows, etc.), if they know how to call it.

Things become interesting when there are more than one presentation layers calling multiple business layers. What would be an optimized way of handling such a situation?

Let us understand the problem with an example.

Consider the IT Infrastructure of an Pension Company – ABC Pension. ABC Pension calculates Pension benefits for employees of its 100+ clients. Each client has a different rule for pension calculation based on their needs. ABC Pension has to deliver Pension Information for all its clients through a single IT Infrastructure.

Let us consider that it has two types of UI Presentation layers:

  1. Java based web site – For users to log in through their credentials and check their account
  2. A Desktop based application used by the phone representatives who attend when a customer calls the company’s toll free help line. This can be in VC++, VB.NET, or C# or any other. The desktop based application renders more information to the phone reps than the website.

Each client of the ABC Pension Company is identified by a client code. When a person logs into the database with his SSN and secured password, the system gets its client id. The communication between the presentation layers and the business layer happens through XML.

There is a separate team of developers, highly trained in the pension domain, to manage the actual pension calculation logic in the Application layer. Each client has separated a separate code library to implement its own business logic.

For example – Client A has a separate code library for its employees; Client B has a separate set of code libraries for its employees. When an employee from company A logs in to the website, the presentation layer has to call the business logic A set of libraries. Similarly, when an employee from Company B logs in to the website layer, the presentation layer has to call the business logic B set of libraries.

How Can This Be Achieved?

Solution

The most optimized way of handling this is described through the attached sample code. For the sake of simplicity, we will take three clients with 3 business logics – BusinessLogic-1, BusinessLogic-2, BusinessLogic-3.

The ideal way to go about it would be to create a “Business Logic Manager” which will decide which business logic to call based on the client id that has been passed to it.

In this project, the Dynamic Assembly Loader console application does this job. For simplicity sake, this is a console application and the choice for business logic is entered through an user input through console. This can be a WCF service or any other project type in real time scenario.

The 1st part is to create a BusinessLogicLibrary – abstraction. This contains:

  1. Abstract class – AbstractBusinessLogic
    namespace BusinessLogicLibrary
    {
        public abstract class AbstractBusinessLogic: IBusinessLogic
        {
            virtual public string GetBusinesslogic()
            {
                throw new NotImplementedException();
            }        
        }
    }
  2. Interface – IbusinessLogic
    namespace BusinessLogicLibrary
    {
        public interface IBusinessLogic
        {
            string GetBusinesslogic();
        }
    }

Note – The method in the abstract class has been declared virtual so that it can be overridden by the methods implementing the actual business logic.

Now, let us construct the three Business Logic code libraries. Here I have used simple class libraries which return a String identifying from which they have been called. For example – if Business Logic 1 is called, then it will return “Calculated Busines Logic 1”. In real time, this can be an XML document returning the Pension plan values for Client -1.

Code for Business Logic - 1

namespace BusinessLogic_1
{
    public class BusinessLogic_1: AbstractBusinessLogic
    {

        public override string GetBusinesslogic()
        {
            return "Calculated Business Logic 1";
        }
    }
}

Code for Business Logic - 2

namespace BusinessLogic_2
{
    public class BusinessLogic_2:AbstractBusinessLogic
    {
        public override string  GetBusinesslogic()

        {
            return "Calculated Business Logic 2";
        }
    }
}

Code for Business Logic - 3

namespace BusinessLogic_3
{
    public class BusinessLogic_3:AbstractBusinessLogic
    {
        public override string  GetBusinesslogic()

        {
            return "Calculated Business Logic 3";
        }
    }
}

Note that the Business Logic class libraries inherits from the AbstractBusinessLogic abstract class and overrides the GetBusinessLogic() method.

Now comes the main part – Dynamic Assembly Loader. This is our Business Logic Manager which decides which Business Logic DLL to load in the memory based on the input.

Add assembly reference to the following first:

  1. System.Configuration and
  2. BusinessLogicLibrary
  3. BusinessLogic-1
  4. BusinessLogic-2
  5. BusinessLogic-3

Add the following in the app.config file:

<configuration>
  <appSettings>
    <add key="BusinessLogic1" value="BusinessLogic_1.BusinessLogic_1,BusinessLogic-1"/>
    <add key="BusinessLogic2" value="BusinessLogic_2.BusinessLogic_2,BusinessLogic-2"/>
    <add key="BusinessLogic3" value="BusinessLogic_3.BusinessLogic_3,BusinessLogic-3"/>
  </appSettings>
</configuration>

Note that the value for the appsettings should be the fully qualified assembly name – namespace.class, assemblename.

Declare an instance of the IbusinessLogic Interface. Remember the Business Logic classes implement the IbusinessLogicInterface.

IBusinessLogic businessLogic = null;

Ask user for input:

Console.WriteLine("Press ....");
Console.WriteLine("1 --- For Business Logic 1");
Console.WriteLine("2 --- For Business Logic 2");
Console.WriteLine("3 --- For Business Logic 3");
Console.WriteLine("Enter your choice");

string choice = Console.ReadLine();
string strbusinessLogicType=null;

Then based on the user choice, get the fully qualified name of the assembly to load from the App.Config file:

switch (choice)
    {
        case "1":
         strbusinessLogicType = ConfigurationManager.AppSettings.Get("BusinessLogic1");
            businessLogic = ProcessLogic(strbusinessLogicType);                    
            break;
        case "2":
         trbusinessLogicType = ConfigurationManager.AppSettings.Get("BusinessLogic2");
            businessLogic = ProcessLogic(strbusinessLogicType);
            break;
        case "3":
         strbusinessLogicType = ConfigurationManager.AppSettings.Get("BusinessLogic3");
            businessLogic = ProcessLogic(strbusinessLogicType);
            break;
        default:
            break;
        }

Finally, load the DLL in the static method ProcessLogic():

static IBusinessLogic ProcessLogic(string logicName)
        {
            try
            {
                Type businessLogicType = Type.GetType(logicName);
                IBusinessLogic logic= (IBusinessLogic) 
		Activator.CreateInstance(businessLogicType) ;
                if (logic == null)
                {
                    //return null;
                    throw new Exception("Business Logic Not Loaded");
 
                }
                else
                    return logic; 
            }
            catch (Exception ex)
            {
                Console.WriteLine("An exception has occurred");
                Console.WriteLine(ex.Message.ToString());
                return null;
            }
    }

Get the type of the assembly from the name in the app.config file and then dynamically load the assembly by creating an instance. Return the instance created.

Finally, print the result:

Console.WriteLine(businessLogic.GetBusinesslogic());
Console.ReadLine();

History

  • 6th September, 2010: Initial version

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here