1

i am new in Dependency injection. i just got familiar how to implement dependency injection with Interface injection but we know that Dependency injection can be implemented with three way or may be more and those are :-

  1. Interface injection: The service provides an interface which consumers must implement. The interface exposes specific behaviors at run time.
  2. Setter injection: The dependent object exposes a “setter” method to inject the dependency.
  3. Constructor injection: Dependencies are injected through the class constructor

so i am looking for few sample code which can help me to understand how to implement Dependency injection using either Setter injection or Constructor injection using unity. any help with small small code for different way of implementing dependency injection will be appreciated.

i know only Interface injection using unity. here is my code which works fine using Interface injection with unity.

public interface ILogger
{
     void Write(string message);
}

We have define three classes as follows.

public class FileLogger : ILogger
{
     public void Write(string message)
     {
          //Do somthing
     }
}

public class SQLLogger : ILogger
{
     public void Write(string message)
     {
          //Do somthing
     }
}

public class WindowsEventLogger : ILogger
{
     public void Write(string message)
     {
          //Do somthing
     }
}

Need to register and map these classes with interface in configuration file (i.e. app.config).

<configSections>
    <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration"/>
  </configSections>

  <unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
    <alias type="UnityTest.ILogger, UnityTest" alias="ILogger" />
    <namespace name="UnityTest"/>

    <container>
      <register mapTo="UnityTest.FileLogger, UnityTest" name="MyFileLogger" type="ILogger"/>
      <register mapTo="UnityTest.SQLLogger, UnityTest" name="MySQLLogger" type="ILogger"/>
      <register mapTo="UnityTest.WindowsEventLogger, UnityTest" name="MyWindowsEventLogger" type="ILogger"/>
    </container>
</unity>

Note: name attribute is important in register tag.

Finally we have to use this map into our code. So, we have to know that for which one is preferable for specific country.

A dictionary object can be use to keep this mapping as follows.

IDictionary<string, string> loggers = new Dictionary<string, string>();
loggers.Add("USA", "MyFileLogger");
loggers.Add("GBR", "MySQLLogger");
loggers.Add("IN", "MyWindowsEventLogger");

You can populate it from database, xml or another source, and now it's time to call the Write method.

IUnityContainer container = new UnityContainer();
container.LoadConfiguration();

ILogger logger = container.Resolve<ILogger>(loggers[objUser.countryCode]);
logger.Write("Hello World");

New question

I found a sample code for construction injection with unity but still one thing is not clear. Here is the code.

public class CustomerService
{
  public CustomerService(LoggingService myServiceInstance)
  { 
    // work with the dependent instance
    myServiceInstance.WriteToLog("SomeValue");
  }
} 

IUnityContainer uContainer = new UnityContainer();
CustomerService myInstance = uContainer.Resolve<CustomerService>();

When we write uContainer.Resolve<CustomerService>(); then we are not sending any instance of LoggingService class then how we can create instance of CustomerService class because it's constructor require instance of LoggingService.

This area is not clear. Please explain to me how it works.

Another question is [Dependency] attribute: what it does, and when a method needs to be decorated with the [Dependency] attribute.

D Stanley
  • 149,601
  • 11
  • 178
  • 240
Thomas
  • 33,544
  • 126
  • 357
  • 626
  • good point http://stackoverflow.com/questions/2015308/constructor-injection-in-c-unity?rq=1 – Thomas Jan 21 '13 at 19:48

2 Answers2

1

With your code as a base.

if you have some class that depends on ILogger, and you have a default registration for ILogger (a registration without name)

IUnityContainer container = new UnityContainer();

//fixed
//by default RegisterType will create new instance of the type every time 
//the container resolves the dependancy 
container.RegisterType<ILogger,SomeLoggerImplementation>();
container.RegisterType<Foo>();
container.RegisterType<Bar>();

//will create a new instance of SomeLoggerImplementation using a default ctor, pass it to the constructor of Foo and return the instance of Foo
//if SomeLoggerImplementation has some other dependancies they can be registered in the container too! 
var foo = container.Resolve<Foo>();

//will create a new instance of SomeLoggerImplementation using a default ctor, create a new instance of Bar, 
//Set the value of the Property Logger (but not the Logger2), and return the instance of Bar
var bar = container.Resolve<Bar>();

//Constructor injection
public class Foo
{
    private ILogger _logger;
    public Foo(ILogger logger)
    {
        //if Foo is resolved from the container , the value for the logger parameter will be provided from the container
        _logger = logger;
    }
}


//property injection
public class Bar
{
    //If Bar is resolvced from the container the value for the Logger property will also  be provided from the container
    [Dependency]
    public ILogger Logger { get; set; }

    //this will not be injected
    public ILogger Logger2 { get; set; }

    public Bar()
    {
    }
}
Petko Petkov
  • 730
  • 3
  • 7
  • i update my question. please have a look and discuss those points. thanks – Thomas Jan 21 '13 at 13:48
  • 1
    It's the whole point of DI, in your updated example LoggingService or better it should be ILoggingService is a dependancy , the container will automaticly provide an instance for it , provided you have registered an apropriate type mapping. the [Dependancy] attribute is needed so Unity will know for witch property it should provide a value , i will try to update the code in a minute to explain better. – Petko Petkov Jan 21 '13 at 13:53
  • what is the meaning of this line container.Register(); can u plzz show me the implementation of SomeLoggerImplementation class. because things not clear to me. – Thomas Jan 21 '13 at 14:21
  • Register<> is giving the error. so tell me what namespace i need to add. thanks – Thomas Jan 21 '13 at 14:37
  • there is no method call Register<> rather there is method called RegisterType<> – Thomas Jan 21 '13 at 14:42
  • my bad, i was writing out of the top of my head, yes it should be RegisterType. – Petko Petkov Jan 21 '13 at 14:57
  • i just do not understand this line container.RegisterType(); where is the code for this class SomeLoggerImplementation ?? – Thomas Jan 21 '13 at 18:33
  • there isn't any code provided , it's just an example, you can replace it whith anyone of your types as long as they implement the interface – Petko Petkov Jan 22 '13 at 09:36
0

First register the classes to be solved to unity (in this case register Test class to unity). When you try to resolve an instance of Test class using unity, it will resolve ILogger too. You may refer to injection attributes from msdn

setter injection;

public class Test : ITest
{
    [Dependency("MyFileLogger")]
    public ILogger Logger
    {
       get { return iLogger; }
       set { iLogger = value; }
    }
}

constructor injection;

public class Test : ITest
{
    public Test([Dependency("MyFileLogger")] ILogger logger)
    {
         //// you will have an instance of MyFileLogger
    }
}

For the second part of your question, since LoggingService is also registered to unity, when CustomerService is tried to be resolved, it will use constructor injection to resolve the LoggingService parameter. In other words, when container tries to resolve CustomerService; it understands that LoggingService is needed to resolve it. Then it first resolves LoggingService parameter and then tries to resolve CustomerService.

daryal
  • 14,643
  • 4
  • 38
  • 54
  • i update my question. please have a look and discuss those points. thanks – Thomas Jan 21 '13 at 13:49
  • why u hard code the dependency class name like [Dependency("MyFileLogger")] or public Test([Dependency("MyFileLogger")] ILogger logger) is it mandatory. thanks – Thomas Jan 21 '13 at 13:51
  • since you have more than one logger, you need to specify the name of the logger to be used. If you were to write only ILogger, then it would not possible to decide which logger to be used. – daryal Jan 21 '13 at 13:55
  • in my question i have come with sample code by which i decide which one i will use at runtime but in ur code u fix the class name. so every time MyFileLogger will be use in ur case. am i right? – Thomas Jan 21 '13 at 14:15
  • @Thomas, you are right; with constructor injection or setter injection you need to provide the mapping to be used. There is no way to do this dynamically. (on the otherhand you may use constructor injection parameters but this is out of scope). – daryal Jan 21 '13 at 14:22
  • can u plzz write a full sample code which i can run at my end. – Thomas Jan 21 '13 at 14:28