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:

Presentation Layer – which forms the user interface to the application

Application Layer – which handles the business logic

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:

Java based web site – For users to log in through their credentials and check their account

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:

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.

Comments and Discussions

I got a 'NullReferenceException was unhandled' runtime error when reaching logic 'Console.WriteLine(businessLogic.GetBusinesslogic());'? Could you please shed some light on it? Maybe I missed out something.

I agree. The abstract class doesn't add anything, and diverts focus from the important bits.

An example of loading an unknown DLL that implements a known interface might be apropos to replace it, e.g. scan a directory, find assemblies containing types that implement the desired interface, then pick one & activate it.

In a more fully developed implementation, your abstract class could contain some additional methods, not all of which need to be overriden, and not all of which need to be marked virtual. Or there may be some private (not protected) methods you don't want derived classes to mess with.

A slight change I would make is that I would declare the virtual method as abstract instead. It feels like derived classes should be required to implement this method. We want a compilation error if a derived class doesn't override this method, rather than a runtime NotImplementedException if a derived class does not override the method.

You could get away with no interface, but the interface is helpful if you're going to be using this with WCF, across AppDomain boundaries, or in advanced scenarios with dependency injection via Castle.Windsor or something like it.

And if you're not using dependency injection, the abstract base class should probably have a public static IBusinessLogic GetBusinessLogic(string name) method that decides based on the string argument which specific derived class to create and return. That way it's not the responsibility of calling code to choose the correct implementation.

Yes correct, The abstract class is not needed and an interface can solve the matter in this case. The abstract class was provided more like a template. It could come to use in much more complex situations to implement methods / properties that child classes can inherit if the situation demands.