home » articles » Dependency Injection And Factory Design

Dependency Injection And Factory Design

change text size: A A A

2/3/2009 by vivek_iit

Introduction

Dependency Injection and Factory design patterns are very common and provide great flexibility in software development.
Though most programmers have read these patterns but they may not grasp the concepts completely unless they see these patterns in action in real projects.

The aim of this article is to provide a detailed explanation on how loose coupling and “plug-and-play” architecture is achieved using these patterns with the help of an open source project I have developed called NeekProtect.

Background

NeekProtect is a simple and user friendly file and folder encryption program to be used on Win 32 platform. It is developed using C# on using Visual Studio 2005. It currently does not use any database.

Now many would ask: why another encryption program? The reason: I was not satisfied with NeoCrypt (another opens source encryption program) as it lacked interactive GUI and was limited in the sense it used a custom library for its encryption algorithms and algorithms can become outdated (3DES was super ceded by Rijndael).
I wanted a flexible "plug-n-play" system where the user can plug his own custom algorithm and make NeekProtect use it by just adding some info in a config file.

My article focuses on this particular requirement and how I achieved it by making use of some famous design patterns,including Dependency Injection and Factory design.

Dependency Injection And Factory Design

Dependency Injection design pattern is “a form of” Inversion of Control design applied in many frameworks such as PicoContainer. It gives the flexibility of attaching custom implementation like a “plugin” without modifying existing software. Dependency Injection can be achieved using Constructor, Setter or Interface Injection. Since Martin Fowler has already written an excellent article on this topic, I would not reproduce it and instead give the link so that the reader can go through the same:

http://www.martinfowler.com/articles/injection.html

Factory Design is a creational pattern is a way through which we delegate the responsibility of object
creation of a particular class to some other “factory class”. For more details please refer:
 
http://en.wikipedia.org/wiki/Factory_method_pattern

Application of Design Patterns

Starting with NeekProtect’s design, since I wanted “plug-and-play” flexibility, I authored an interface
first so that others can implement their own algorithmic implementations by defining these methods in their own custom way:

namespace NeekProtect
{
    /// <summary>
    /// This interface is the contract which implementation classes
    /// need to follow for writing custom encryption methods.
    /// </summary>
    public interface IEncryptionAlgorithm
    {
        /// <summary>
        /// Property to get/set password
        /// </summary>
        string Password
        {
            get;
            set;
        }

        /// <summary>
        /// Property to get/set the Raw Input byte array
        /// </summary>
        byte[] RawInput
        {
            get;
            set;
        }

        /// <summary>
        /// Set optional salt value
        /// </summary>
        byte[] Salt
        {
            set;
        }

        /// <summary>
        /// Set KeySize
        /// </summary>
        int KeySize
        {
            set;
        }

        /// <summary>
        /// Encrypts the raw input
        /// </summary>
        /// <returns>Encrypted byte array</returns>
        byte[] Encrypt();

        /// <summary>
        /// Decrypts the byte array
        /// </summary>
        /// <returns>Decrypted bytes</returns>
        byte[] Decrypt();

        /// <summary>
        /// Checks the user entered password. The password is stored in the
        /// encrypted byte array and is first compared before decryption.
        /// </summary>
        /// <returns>true if password is correct</returns>
        bool CheckPassword();
       
    }//end interface
}//end namespacenamespace NeekProtect
{
    /// <summary>
    /// This interface is the contract which implementation classes
    /// need to follow for writing custom encryption methods.
    /// </summary>
    public interface IEncryptionAlgorithm
    {
        /// <summary>
        /// Property to get/set password
        /// </summary>
        string Password
        {
            get;
            set;
        }

        /// <summary>
        /// Property to get/set the Raw Input byte array
        /// </summary>
        byte[] RawInput
        {
            get;
            set;
        }

        /// <summary>
        /// Set optional salt value
        /// </summary>
        byte[] Salt
        {
            set;
        }

        /// <summary>
        /// Set KeySize
        /// </summary>
        int KeySize
        {
            set;
        }

        /// <summary>
        /// Encrypts the raw input
        /// </summary>
        /// <returns>Encrypted byte array</returns>
        byte[] Encrypt();

        /// <summary>
        /// Decrypts the byte array
        /// </summary>
        /// <returns>Decrypted bytes</returns>
        byte[] Decrypt();

        /// <summary>
        /// Checks the user entered password. The password is stored in the
        /// encrypted byte array and is first compared before decryption.
        /// </summary>
        /// <returns>true if password is correct</returns>
        bool CheckPassword();
       
    }//end interface
}//end namespace

Now I first created an XOR based encryption class which implemented this interface:

public class XOREncryption : IEncryptionAlgorithm

I implemented the encryption and decryption methods along with the propertied defined in the IEncryptionAlgorithm interface as:

/// <summary>
/// Main encryption method
        /// </summary>
        /// <returns>Array of bytes containing encrypted output</returns>
        public byte[] Encrypt()
        {
            ///<remarks>
            ///Output byte array
            ///</remarks>
            byte[] encryptedBytes = new byte[_rawInput.Length];
            byte[] keyBytes = ASCIIEncoding.ASCII.GetBytes(_key);
            //hard coded salt value
            _salt = new byte[] {0x11, 0x78, 0x22, 0xFF, 0xAC, 0x5C,
                                0x78, 0x4E, 0x7D, 0x45, 0xEF, 0xF1};
              …..//implementation
         }

I completed this class with other methods and properties defined by the interface (see the source code).
Then I created another encryption algorithm implementation:

public class RijndaelEncryption : IEncryptionAlgorithm
{
       //implement IEncryptionAlgorithm properties and methods
}

So now I have two implementations ready and the question is how do I dynamically instantiate one of these in the GUI?

For that, I used Factory Design Pattern and created a Factory class as:

namespace NeekProtect
{
    /// <summary>
    /// This factory class is responsible for creation of concerete
    /// instances of different algorithm implementations.
    /// </summary>
    public sealed class AlgorithmFactory
    {
        /// <summary>
        /// Private constrcutor so as to avoid instance creation
        /// </summary>
        private AlgorithmFactory()
        { }

        /// <summary>B
        /// Static method which the client will call to get
        /// the current concrete implementation specified in the
        /// configuration settings file
        /// </summary>
        public static IEncryptionAlgorithm GetSpecifiedAlgorithm()
        {
            string algoType = System.Configuration.ConfigurationSettings.AppSettings["algo"];
            IEncryptionAlgorithm algoInstance;

            if (string.IsNullOrEmpty(algoType))
            {
                ///<remarks>
                ///Use default XOR encryption
                ///</remarks>
algoInstance = Activator.CreateInstance(Type.GetType("NeekProtect.XOREncryption,NeekProtect"))
                     as IEncryptionAlgorithm;
            }
            else
            {
                algoInstance = Activator.CreateInstance(Type.GetType(algoType)) as IEncryptionAlgorithm;
            }
            ///<remarks>
            ///Return the appropriate IEncryptionAlgorithm concrete instance
            ///</remarks>
            return algoInstance;
        }
    }//end class
}//end namespace

This factory class is sealed because I don’t see any one ineheriting it for any reason. Then I made its
constructor private so that its instance cannot be created at all and made all methods static. Why static? Because AlgorithmFactory is behacing like a Helper class helping the clients get an instance of appropriate Algorithm implementation class.
See the static GetSpecifiedAlgorithm() method: it returns an instance of IEncryptionAlgorithm. This is where I used an important Design principle: “Always program to interfaces”. Since each encryption algorithm class implements IEncryptionAlgorithm, so the supertype of each implementation is same: IEncryptionAlgorithm.
So I don’t care about the actual implementation class as long as the class implements the same interface.

 This gets me the type specified in the application config file:

string algoType = System.Configuration.ConfigurationSettings.AppSettings["algo"];

In the config file, the following entry is made (under appSettings):

<add key="algo" value="NeekProtect.XOREncryption,NeekProtect"/>

In the value, we specify the fully qualified class name and the assembly name in which the class is present,separated by a comma.We need this entry as we will dynamically load the assembly using Activator.CreateInstance as:

IEncryptionAlgorithm algoInstance;
algoInstance = Activator.CreateInstance(Type.GetType(algoTyp)) as IEncryptionAlgorithm;

Note: If no entry is specified in the config file then XOREncryption class is used as default
(see the code for AlgorithmFactory)algoInstance is then returned to the client caller.

Lets see the client now and how it uses this instance. The class EncryptionEngine is our client here:

/// <summary>
/// This class prepares the byte array and sets files and directories to
/// be encrypted and calls the relevant encryption/decryption algorithm
/// </summary>
    public class EncryptionEngine
{ ….}

This class has a method:

private void EncryptFile(string fullPath, string password)
   {
               IEncryptionAlgorithm x = AlgorithmFactory.GetSpecifiedAlgorithm();
                x.Password = password;
                x.KeySize = 128;
                string ext = Path.GetExtension(fullPath);
                byte[] extByte = Encoding.ASCII.GetBytes(ext);
                byte[] inputByte = File.ReadAllBytes(fullPath);
                MemoryStream m = new MemoryStream();
                m.Write(inputByte, 0, inputByte.Length);
                m.Write(extByte, 0, extByte.Length);
                x.RawInput = m.ToArray();
                byte[] o = x.Encrypt();
                …..//other stuff
}

So I call the AlgorithmFactory’s static method GetSpecifiedAlgorithm() which returns me an instance of the class specified in the config file. Here I don’t care how does the instance is returned, I just need
an instance of IEncryptionAlgorithm so that I can encrypt the input file. This is again an example of
programming to interfaces. In the above code, there is no mention of the 2 encryption classes I have coded earlier: XOREncryption and RijndaelEncryption. I only use IEncryptionAlgorithm in this code and this gives me the flexilbity to use any custom alorithm as long as it imeplements EncryptionAlgorithm. Lets suppose a user installs NeekProtect and is not satisfied by my provided two alogrithms. Assume he wished to use 3DES algorithm to use with NeekProtect. What does he do?

Answer: Create his own 3DESEncryption class and implement all methods and proeprties specified in
the IEncryptionAlgorithm interface as:

public class 3DESEncryption: IEncryptionAlgorithm
{
       //implement IEncryptionAlgorithm properties and methods
}

Now compile it and place the resultant assembly in the folder where NeekProtect is installed
(for e.g.: C:\Program Files\Vivek Thakur\NeekProtect 1.1b).
In the same folder, open and edit the XML configuration file (usually its named as NeekProtect.GUI.exe.config) and create/overwrite the value of the key “algo” as:

<add key="algo" value="MyCustomAlgo.3DESEncryption, MyCustomAlgo "/>

(for the sake of illustration, I have assumed the namespace to be MyCustomAlgo)

Now the Factory class will return this instance to be used in NeekProtect. So we see how "plugin" type functionality can be achieved using Dependency Injection.

Summary

Using simple design patterns can help create flexible software which is also easy to maintain and also reduce costs. By the help of this article I wanted to explain how this flexibility can be achieved in
real world programs. Also if there are any suggestions on improving this design, I would love to hear them.

To rate this article please register or login

Author

vivek_iit vivek_iit (Member since:11/27/2008)
I am one of the administrators at CodeAsp.Net and I love programming, architecting solutions, code reviews, teaching and writing about ASP.NET.

Comments (no comments yet)

Post a comment

Comment (No HTML)  

Type the characters:
 *
 
   

Related articles

Join CodeAsp.Net for FREE Today!

It's fast, easy and free! Submit articles, get your own blog, ask questions & give answers in the forums, and become a better developer, faster.

enter your email address:

Latest Articles RSS Feed

Latest Articles

  • Hi Friends, Many times we came cross the requirement when we need to access the dropdownlist's selectedindexchanged event inside the gridview, like in a shopping cart changing the item's quantity or binding the other dropdown based on the first dropdown.
  • This is the approach that I have adopted to develop Expandable / Collapsible Panel Control through JavaScript. Please report bugs, errors and suggestions to improve this control.
  • This is my approach to develop custom JavaScript ListBox control. Although it is only a subset of existing HTML ListBox element, it is more user friendly than the existing one. It can be further customized for different requirements. Please let me know about bugs and/or errors & give suggestions to improve this ListBox control.
  • I have tried my best to make this user control code error free. I will most welcome suggestions for further improvement in this user control. I have tested this user control on various browsers and it works fine.
  • So, this is my approach to implement an ASP.NET slide show using the DataList. I have tried my best to keep it bug free. I will most welcome suggestions and criticism for further improvements of this user control. I have tested this user control on various browsers and it works fine.
  • As we all knows that Repeater and DataList does not have auto paging support technique like Gridview or Datagrid, but we can achieve this through PagedDataSource. By using PagedDataSource we can implement paging in Repeater or DataList. Now in our mind there is question arise what is PagedDataSource. PagedDataSource is a class which encapsulates
  • So this is my approach. I was working for a long time to create C# like event handlers for JavaScript classes and finally, I’ve done it. Please let me know of any bugs and suggestions to improve this context menu control.
  • So this is my solution. If you have some other ideas about this functionality, please share them with me.
  • I have tried my best to make this code error free. Suggestions and criticism for further improvements of this code are most welcome.
  • So this is the approach that I've adopted to solve the Hover Delay problem. Although originally I developed Hover Delay to deactivate the click event for 1 second on a GridView row, later I also used Hover Delay to deactivate Drag n Drop of GridView rows. Kindly let me know if any one has some other better or different solution.
  • In this article I will explain how to import data from EXCEL to SQL in ASP.NET . In many situations we have data in the form of excel sheet but we have the requirement to have that data in SQL SERVER DB. I have explained importing data both from Excel 97-2003 as well as Excel 2007 format.
  • The source code shows how to use Regular Expressions in C#. The code Functions written for Validation Alphabet, AlphaNumeric, Integer, Postive Integer, Floating point numbers. You just cut copy these functions and use in any program.
  • That’s all about this technique. Just download the sample application and happy CSS! I have tested this application on various browsers and it worked fine.
  • This script is cross-browser compatible and fast as it iterates elements of a specific tag inside a target element [GridView] rather than iterating in a whole form. It searches the elements of a specific type in a particular column of the target element [GridView].
  • This Article is used to insert a numeric value on the sever control(text box) This is a java script code for the the client side validation. On Page Load Event You can change the events in txtNoOfQuestion.Attributes.Add("onkeypress", "return numericOnly(this);"); like onfocus events like other according to needs.
  • I have toggled visibility of all TD elements of a GridView column in order to create an illusion of smooth dynamic effect with the help of setTimeout method through recursion. Different browsers have different effects of Expanding / Collapsing GridView Columns. In Internet Explorer 7/8, Safari, Google Chrome and Opera, it seems that columns are Exp
  • In this article, I've used the setTimeout method in order to achieve a smooth expand/collapse functionality.
  • Introduction I am going to present here a functionality that selects / deselects all checkboxes of a particular column inside a GridView control, provided the header checkbox of that column is checked or unchecked using JavaScript. This functionality also has a feature that when all checkboxes of a particular column inside the GridView are check
  • This article describes how to toggle the states of all CheckBoxes inside a particular DataGridView column.
  • This article describes how to apply client-side mouse over & mouse out effects on the GridView’s rows.