Click here to Skip to main content
15,867,453 members
Articles / Web Development / ASP.NET

Dependency Injection with ObjectPoolManager (OPM)

Rate me:
Please Sign up or sign in to vote.
5.00/5 (11 votes)
31 Oct 2010CPOL5 min read 45.7K   510   33   12
Lightweight and simple

Introduction

Recently I got my hands over some of the IOC tools available for .NET and really liked the concept of dependency injection from starting stage of application and invoking / utilizing it whenever required. The only thing that was not making me using it for fun was too many complexities introduced in them over the period of time.

As conceptually this technique is not that “I can’t do it” hard, for the sake of fun, I decided to make my own.

Followings are the list of .NET IOC tools available (in order of my choices):

  1. Ninject
  2. Unity
  3. Windsor
  4. StructureMap

Definition

According to Wikipedia

“Dependency injection (DI) in object-oriented computer programming is a design pattern with a core principle of separating behavior from dependency resolution. In other words: a technique for decoupling highly dependent software components.”

Benefits

Traditionally developers used to hard code the dependencies as and when it’s required which makes that piece of code tightly coupled and needs to be changed over the period of time if any requirement changes. That certainly violates the DRY principle as the developer may need to modify the entire flow of code or make copies of methods to support only that change.

Dependency Injection could help over this situation with the implementation of Interface that provides the required functionality to end user. DI framework could load the object inherited from this interface which is actually injected much before its utilization whenever possible at runtime.

DI framework need not to be limited by this phenomenon, it actually overcomes many of the routine problems that a developer could come across. Another such example is like developer wants to utilize certain class, but is not sure about the inputs needed to make this class usable. In such a situation, the responsible module could take care of this class for providing inputs using DI and let developers use its instance just by refereeing its name or type.

According to Wikipedia

Dependency injection is a specific form of inversion of control where the concern being inverted is the process of obtaining the needed dependency.

Introducing “ObjectPoolManager” (OPM) Framework

Well it’s a lightweight dependency injector container and currently at development phase yet complete to achieve most of the common needs that every DI framework need to do. Currently this framework has been tested along a number of test cases that I thought to have in it as initial draft. Certainly it lacks some of the features that Ninject and Unity have, but I’ll keep on upgrading this as time permits. As of now, it does help to reduce boilerplate code.

Design Highlights

Design.png

The above module illustrates the current implementation of this DI framework. Whenever user injects the type or object, it maintains it inside Object container which is accessible internally by framework only. Currently this framework supports pool with and without Context. Context here means simply a catalog of types/object registered under that key. This helps user to register same types in different Contexts and with same names as well.

ObjectPoolManager Class

(Static) Maintains the object pools and contexts of pools:

Properties

Pool Provides the non-context based Object Pool
Context Collection of contexts that holds Object Pools

Methods

Clear Clears Object container

ObjectPool Class

Registers and resolves the objects:

Properties

Context Name of context pool belongs to

Methods

Register(string, object) Registers the object as singleton for provided string name.
Register<T>() Registers the class type for default constructor.
Register<T>(ObjectScope) Registers the class type for default constructor using specified scope.
Register<T>(string) Registers the class type for default constructor using specified name.
Register<T>(string, ObjectScope) Registers the class type for default constructor using specified scope string name.
Register<T>(Func<T>) Registers the class type using provided delegate.
Register<T>(Func<T>, ObjectScope) Registers the class type using provided delegate and scope.
Register<T>(string, Func<T>) Registers the class type using provided delegate and string name.
Register<T>(string, Func<T>, ObjectScope) Registers the class type using provided delegate and scope and string name.
Register<I, T>() Registers the class type T for default constructor and binds its return type to I.
Register<I, T>(ObjectScope) Registers the class type for default constructor using specified scope and binds its return type to I.
Register<I, T>(string) Registers the class type for default constructor using specified name and binds its return type to I.
Register<I, T>(string, ObjectScope) Registers the class type for default constructor using specified scope string name and binds its return type to I.
Register<I, T>(Func<T>) Registers the class type using provided delegate and binds its return type to I.
Register<I, T>(Func<T>, ObjectScope) Registers the class type using provided delegate and scope and binds its return type to I.
Register<I, T>(string, Func<T>) Registers the class type using provided delegate and string name and binds its return type to I.
Register<I, T>(string, Func<T>, ObjectScope) Registers the class type using provided delegate and scope and string name and binds its return type to I.
Resolve(string) Returns object using specified string name. This can only be used for objects registered with Register(string, object)
Resolve<T>() Returns object of type T that has been registered in current accessed pool.
Resolve<T>(string) Returns object of type T that has been registered in current accessed pool using specified string name
BeginResolve<T>(string, ObjectInvokeCallback) Begins to resolving the object registered with delegate.
Dispose() Disposes the current pool.

ObjectScope enum

<p>None </p>

Tells contained to create new object every time when invoked

Singleton

Returns the same object after invoking first time

ObjectInvokeArgument Class

EventArgument returned on calling BeginResolve on ObjectInvokeCallback:

Properties

Context Name of context callback called on.
Name Name used for registering the object type
Result Object returned from Async invoke

Example Application

Consider the following example implementing RR layout for Farrari F430:

C#
public interface IDriveLayout
{
    string Name { get; }
}

public interface IEngineLayout
{
    string Name { get; }
}

class RearMidEngine : IEngineLayout
{
    public string Name
    {
        get { return "Rear Mid Engine"; }
    }
}

public class RearWheelDrive : IDriveLayout
{
    public string Name
    {
        get { return "Rear Wheel Drive"; }
    }
}

public class Vehicle
{
    private IDriveLayout _driveLayout;
    private IEngineLayout _engineLayout;

    public string DriveType
    {
        get { return _driveLayout.Name; }
    }

    public string EngineType
    {
        get { return _engineLayout.Name; }
    }

    public virtual string Name
    {
        get { return "Vehicle"; }
    }

    public Vehicle(IDriveLayout driveLayout, IEngineLayout engineLayout)
    {
        _driveLayout = driveLayout;
        _engineLayout = engineLayout;
    }
}

class FerrariF430 : Vehicle
{
    public FerrariF430(IDriveLayout driveLayout, IEngineLayout engineLayout)
        : base(driveLayout, engineLayout)
    { }

    public override string Name
    {
        get
        {
            return "Ferrari F430";
        }
    }
}

Registering Classes

C#
ObjectPoolManager.Pool.Register<IDriveLayout, RearWheelDrive>("RearWheelDrive");
ObjectPoolManager.Pool.Register<IEngineLayout, RearMidEngine>("RearMidEngine");

ObjectPoolManager.Pool.Register<Vehicle, FerrariF430>("FerrariF430", () => 
                new FerrariF430(
                       ObjectPoolManager.Pool.Resolve<IDriveLayout>("RearWheelDrive"),
                       ObjectPoolManager.Pool.Resolve<IEngineLayout>("RearMidEngine")
                ));

Retrieving Classes

C#
var vehicle = ObjectPoolManager.Pool.Resolve<Vehicle>"FerrariF430");
Console.WriteLine("{0} -> Layout: {1}, {2}", 
	vehicle.Name, vehicle.EngineType, vehicle.DriveType);
Console.ReadLine();

Also refer to Test cases included in the source code for more examples.

TODO

  1. Attribute support for constructor injection and methods injection
  2. Configurable registration support (in XML)

History

  • 31st October, 2010 – v0.8 Beta released

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralMy vote of 5 Pin
justinonday17-Feb-11 22:35
justinonday17-Feb-11 22:35 
GeneralMy vote of 5 Pin
robvon20-Nov-10 13:19
robvon20-Nov-10 13:19 
GeneralNice project Pin
FantasticFiasco17-Nov-10 19:06
FantasticFiasco17-Nov-10 19:06 
GeneralGood one Pin
Rajesh Pillai2-Nov-10 7:54
Rajesh Pillai2-Nov-10 7:54 
GeneralRe: Good one Pin
NavnathKale2-Nov-10 9:09
NavnathKale2-Nov-10 9:09 
GeneralI too felt as you did Navnath, Prism, Unity, and the like we're cool, but...... Pin
Your Display Name Here1-Nov-10 6:49
Your Display Name Here1-Nov-10 6:49 
GeneralRe: I too felt as you did Navnath, Prism, Unity, and the like we're cool, but...... Pin
NavnathKale2-Nov-10 6:45
NavnathKale2-Nov-10 6:45 
GeneralMmmmm [modified] Pin
Sacha Barber1-Nov-10 1:53
Sacha Barber1-Nov-10 1:53 
GeneralRe: Mmmmm Pin
NavnathKale1-Nov-10 2:16
NavnathKale1-Nov-10 2:16 
GeneralRe: Mmmmm Pin
NavnathKale2-Nov-10 9:08
NavnathKale2-Nov-10 9:08 
Generalsuggestion Pin
Seishin#31-Oct-10 22:24
Seishin#31-Oct-10 22:24 
use custom Attributes to mark classes to register
implement a manager class which will automatically pick those marked classes and register them..
pattern can be used in many other applications like binding commands with triggers..
life is study!!!

GeneralRe: suggestion Pin
NavnathKale31-Oct-10 22:59
NavnathKale31-Oct-10 22:59 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.