Three main styles of dependency injection
From Logic Wiki
Contents
Constructor Injection (most common & recommended)
Idea :
Dependencies are provided through the constructor. If the object exists, its dependencies must exist too.
Example
public interface ILogger
{
void Log(string message);
}
public class ConsoleLogger : ILogger
{
public void Log(string message)
{
Console.WriteLine(message);
}
}
public class OrderService
{
private readonly ILogger _logger;
public OrderService(ILogger logger) // injected here
{
_logger = logger;
}
public void PlaceOrder()
{
_logger.Log("Order placed");
}
}
<pre>
=== Usage ===
<pre>
ILogger logger = new ConsoleLogger();
OrderService service = new OrderService(logger);
service.PlaceOrder();
Pros and Cons
✅ Pros
- Dependencies are mandatory
- Class is always in a valid state
- Easy to test
- Works perfectly with DI containers
❌ Cons
- Constructor can get long if there are many dependencies
Setter Injection (Property Injection)
Idea :
Dependencies are assigned through public properties after the object is created.
Example
public class OrderService
{
public ILogger Logger { get; set; } // injected via property
public void PlaceOrder()
{
Logger?.Log("Order placed");
}
}
Usage
OrderService service = new OrderService(); service.Logger = new ConsoleLogger(); service.PlaceOrder();
Pros and Cons
✅ Pros
- Useful for optional dependencies
- Flexible
- Cleaner constructor
❌ Cons
- Object can exist in an invalid state
- Dependency might be forgotten
- Harder to enforce correctness
Interface Injection (rarely used)
Idea :
The dependency provides itself via a special interface method.
Example
public interface ILogger
{
void Log(string message);
}
public interface ILoggerAware
{
void SetLogger(ILogger logger);
}
public class OrderService : ILoggerAware
{
private ILogger _logger;
public void SetLogger(ILogger logger)
{
_logger = logger;
}
public void PlaceOrder()
{
_logger.Log("Order placed");
}
}
Usage
OrderService service = new OrderService(); service.SetLogger(new ConsoleLogger()); service.PlaceOrder();
Pros and Cons
✅ Pros
- Explicit injection contract
- Dependency clearly declared
❌ Cons
- More boilerplate
- Not supported by most DI containers
- Rare in real-world C# apps