views:

735

answers:

7

Can someone explain dependency injection with a basic .NET example and provide a few links to .NET resources to extend on the subject?

This is not a duplicate of http://stackoverflow.com/questions/130794/what-is-dependency-injection because I am asking about specific .NET examples and resources.

A: 

You essentially pass in all necessary objects in the constructor. Alternatively, you can resolve them at runtime using an interface resolver (although this is less typesafe). You can find excellent examples at the Ninject website for the first approach, and good examples at the Unity website for the second approach. This avoid the need for singletons and allows you to easily drop in a replacement object that conforms to the desired interface

Steve
+4  A: 

Take a look at the following articles that may provide some help on this:

General link about the container:

Couple of SO links that may help further things on the subject:

JB King
+1  A: 

Martin Fowler has the description covered: http://martinfowler.com/articles/injection.html

As far as .NET resources go take a look at:

Codebrain
+10  A: 

Here's a common example. You need to log in your application. But, at design time, you're not sure if the client wants to log to a database, files, or the event log.

So, you want to use DI to defer that choice to one that can be configured by the client.

This is some pseudocode (roughly based on Unity):

You create a logging interface:

public interface ILog
{
  void Log(string text);
}

then use this interface in your classes

public class SomeClass
{
  [Dependency]
  public ILog Log {get;set;}
}

inject those dependencies at runtime

public class SomeClassFactory
{
  public SomeClass Create()
  {
    var result = new SomeClass();
    DependencyInjector.Inject(result);
    return result;
  }
}

and the instance is configured in app.config:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <section name ="unity"
             type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,
              Microsoft.Practices.Unity.Configuration"/>
  </configSections>
  <unity>
    <typeAliases>
      <typeAlias alias="singleton"
                 type="Microsoft.Practices.Unity.ContainerControlledLifetimeManager,Microsoft.Practices.Unity" />
    </typeAliases>
    <containers>
      <container>
        <types>
          <type type="MyAssembly.ILog,MyAssembly"
                mapTo="MyImplementations.SqlLog, MyImplementations">
            <lifetime type="singleton"/>
          </type>
        </types>
      </container>
    </containers>
  </unity>
</configuration>

Now if you want to change the type of logger, you just go into the configuration and specify another type.

Will
... or you use Log4Net which already supports both file and database log appenders. You can also write your own appender if the built in do not fit your needs.
Johnny Egeland
That's not the point.
Will
it's not indeed :) - thanks for the useful example
JohnIdol
+1  A: 

I've got Dependency Injection with a really simple example like this.

See the class below, you'll get the whole idea. As you see unless you supply file it will use the default one settings file, but you can set a settings file and then the class will use it.

Public Class ProcessFile

Private _SettingsFile As String = "settings.bin"

Public Sub New()
End Sub

Public Sub New(settings As String)
_SettingsFile= settings
End Sub

Public Function ReadFile() As String 
'Do stuff based on the settings stored in the _SettingsFile 
End Function

End Class

Obviously this is the most basic case. In real world you can do the same thing with class types, such as you've got Database Layer and you can switch the underlying database dll by doing dependency injection and you code will work with any database as soon as you can provide the valid class (a class which implements the interface you are using).

After got the basic you can do this on larger scope and totally independent from the application by using DI frameworks like unity.

dr. evil
+3  A: 

Ninject must have one of the coolest sample out there: (pieced from the sample)

interface IWeapon {
  void Hit(string target);
}
class Sword : IWeapon {
  public void Hit(string target) {
    Console.WriteLine("Chopped {0} clean in half", target);
  }
}
class Shuriken : IWeapon {
  public void Hit(string target) {
    Console.WriteLine("Shuriken tossed on {0}", target);
  }
}
class Samurai {
  private IWeapon _weapon;

  [Inject]
  public Samurai(IWeapon weapon) {
    _weapon = weapon;
  }

  public void Attack(string target) {
    _weapon.Hit(target);
  }
}

class WeaponsModule {
  private readonly bool _useMeleeWeapons;

  public WeaponsModule(bool useMeleeWeapons) {
    _useMeleeWeapons = useMeleeWeapons;
  }

  public void Load() {
    if (useMeleeWeapons)
      Bind<IWeapon>().To<Sword>();
    else
      Bind<IWeapon>().To<Shuriken>();
  }
}

class Program {
  public static void Main() {
    bool useMeleeWeapons = false;
    IKernel kernel = new StandardKernel(new WeaponsModule(useMeleeWeapons));
    Samurai warrior = kernel.Get<Samurai>();
    warrior.Attack("the evildoers");
  }
}

This, to me, reads very fluently, before you start up your dojo you can decide how to arm your Samurais.

Sam Saffron