First, let’s examine the idea of dependency injection by walking through a simple example. Let’s say you’re writing the next blockbuster game, where noble warriors do battle for great glory. First, we’ll need a weapon suitable for arming our warriors.
class Sword { public void Hit(string target) { Console.WriteLine("Chopped {0} clean in half", target); } }Then, let’s create a class to represent our warriors themselves. In order to attack its foes, the warrior will need an
Attack()
method. When this method is called, it should use its Sword
to strike its opponent.class Samurai { readonly Sword sword; public Samurai() { this.sword = new Sword(); } public void Attack(string target) { this.sword.Hit(target); } }Now, we can create our Samurai and do battle!
class Program { public static void Main() { var warrior = new Samurai(); warrior.Attack("the evildoers"); } }As you might imagine, this will print Chopped the evildoers clean in half to the console. This works just fine, but what if we wanted to arm our
Samurai
with another weapon? Since the Sword
is created inside the Samurai
class’s constructor, we have to modify the implementation of the class in order to make this change.When a class is dependent on a concrete dependency, it is said to be tightly coupled to that class. In this example, the
Samurai
class is tightly coupled to the Sword
class. When classes are tightly coupled, they cannot be interchanged
without altering their implementation. In order to avoid tightly
coupling classes, we can use interfaces to provide a level of
indirection. Let’s create an interface to represent a weapon in our
game.interface IWeapon { void Hit(string target); }Then, our
Sword
class can implement this interface:class Sword : IWeapon { public void Hit(string target) { Console.WriteLine("Chopped {0} clean in half", target); } }And we can alter our
Samurai
class:class Samurai { readonly IWeapon weapon; public Samurai() { this.weapon = new Sword(); } public void Attack(string target) { this.weapon.Hit(target); } }Now our
Samurai
can be armed with different weapons. But wait! The Sword
is still created inside the constructor of Samurai
. Since we still need to alter the implementation of Samurai
in order to give our warrior another weapon, Samurai
is still tightly coupled to Sword
.Fortunately, there is an easy solution. Rather than creating the
Sword
from within the constructor of Samurai
, we can expose it as a parameter of the constructor instead.class Samurai { readonly IWeapon weapon; public Samurai(IWeapon weapon) { this.weapon = weapon; } public void Attack(string target) { this.weapon.Hit(target); } }Then, to arm our warrior, we can inject the
Sword
via the Samurai
‘s constructor. This is an example of dependency injection (specifically, constructor injection). Let’s create another weapon that our Samurai
could use:class Shuriken : IWeapon { public void Hit(string target) { Console.WriteLine("Pierced {0}'s armor", target); } }Now, we can create an army of warriors:
class Program { public static void Main() { var warrior1 = new Samurai(new Shuriken()); var warrior2 = new Samurai(new Sword()); warrior1.Attack("the evildoers"); warrior2.Attack("the evildoers"); } }This results in the following output to be printed to the console:
Pierced the evildoers armor.This is called dependency injection by hand, because each time you want to create a
Chopped the evildoers clean in half.
Samurai
, you must first create some implementation of IWeapon
and then pass it to the constructor of Samurai
. Now that we can change the weapon the Samurai
uses without having to modify its implementation, the Samurai
class could be in a separate assembly from Sword
– in fact, we can create new weapons without needing the source code of the Samurai
class!Dependency injection by hand is an effective strategy for small projects, but as your application grows in size and complexity, it becomes more and more cumbersome to wire all of your objects up. What happens when the dependencies have dependencies of their own? What happens when you want to add a (e.g. caching, tracing to a log, auditing etc.) decorator in front of each instance of a given dependency? You can easily end up spending most of your time creating and wiring together objects, when you could be writing code that adds real value to your software. This is where dependency injection libraries / frameworks like Ninject can help.
Ref:- Here
For Eg:-
class Client { static void Main(string[] args) { var con1 = new Assembly(new SQLConnection()); Console.Write(con1.WriteConnection() + "\n" ); var con2 = new Assembly(new MySQLConnection()); Console.Write(con2.WriteConnection() + "\n"); var oracle = new Assembly(new OracleConnection()); Console.Write(oracle.WriteConnection()); Console.Read(); } } public interface IConnection { string GetConnection(string con); } public class SQLConnection : IConnection { public string GetConnection(string conn) { return conn; } } public class MySQLConnection : IConnection { public string GetConnection(string conn) { return conn; } } public class OracleConnection : IConnection { public string GetConnection(string con) { return con; } } //This is a assembly which will be loosely coupled in spite of any connection public class Assembly { readonly IConnection objCon; //We inject connection in constructor public Assembly(IConnection conn) { this.objCon = conn; } public string WriteConnection() { return this.objCon.GetConnection(this.objCon.ToString()); } }Thanks,
Amit
Its great :)
ReplyDeleteReally appreciate this wonderful post that you have provided for us.Great site and a great topic as well i really get amazed to read this. Its really good. EPS Pre-Expander machine
ReplyDelete