Reputation: 34188
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 :-
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");
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.
Upvotes: 1
Views: 1018
Reputation: 750
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()
{
}
}
Upvotes: 1
Reputation: 14919
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
.
Upvotes: 0