Dependency injection in c# with an example

Dependency injection in c# with an example

Kamlesh Singh
5 min readJun 5, 2023

--

Dependency injection (DI) is a design pattern commonly used in software development, particularly in object-oriented languages like C#. It promotes loose coupling and modularization by allowing objects to depend on abstractions rather than concrete implementations. This makes code more flexible, maintainable, and testable. In C#, you can implement dependency injection in various ways, such as constructor injection, property injection, or method injection.

  1. Constructor injection:
// Interface representing the dependency
public interface IMessageService
{
void SendMessage(string message);
}

// Concrete implementation of the dependency
public class EmailService : IMessageService
{
public void SendMessage(string message)
{
Console.WriteLine($"Sending email: {message}");
}
}

// Class that depends on the IMessageService
public class NotificationService
{
private readonly IMessageService _messageService;

// Constructor injection
public NotificationService(IMessageService messageService)
{
_messageService = messageService;
}

public void SendNotification(string message)
{
_messageService.SendMessage(message);
}
}

// Usage example
public class Program
{
public static void Main()
{
// Create an instance of the dependency
IMessageService emailService = new EmailService();

// Create an instance of the class with the dependency injected
NotificationService notificationService = new NotificationService(emailService);

// Use the class
notificationService.SendNotification("Hello, world!");
}
}

In the example above, we have an IMessageService interface that defines the contract for a message service. The EmailService class implements this interface and provides the concrete implementation for sending emails.

The NotificationService class depends on the IMessageService interface, which is injected via its constructor. This allows different implementations of IMessageService to be easily swapped without modifying the NotificationService class. The SendNotification method uses the injected IMessageService to send a notification message.

The NotificationService class depends on the IMessageService interface, which is injected via its constructor. This allows different implementations of IMessageService to be easily swapped without modifying the NotificationService class. The SendNotification method uses the injected IMessageService to send a notification message.

2. Property injection:

Property injection is another approach to implementing dependency injection in C#. Instead of injecting dependencies through the constructor, the dependencies are injected through public properties of the dependent class. Here’s an example of property injection:

// Interface representing the dependency
public interface ILogger
{
void Log(string message);
}

// Concrete implementation of the dependency
public class ConsoleLogger : ILogger
{
public void Log(string message)
{
Console.WriteLine($"Logging: {message}");
}
}

// Class that depends on the ILogger
public class UserService
{
// Property injection
public ILogger Logger { get; set; }

public void CreateUser(string username)
{
// Perform user creation logic
Logger.Log($"User '{username}' created successfully.");
}
}

// Usage example
public class Program
{
public static void Main()
{
// Create an instance of the dependent class
UserService userService = new UserService();

// Create an instance of the dependency
ILogger logger = new ConsoleLogger();

// Inject the dependency through the property
userService.Logger = logger;

// Use the dependent class
userService.CreateUser("Dependent");
}
}

In the example above, we have an ILogger interface that defines the contract for a logger. The ConsoleLogger class implements this interface and provides the concrete implementation for logging to the console.

The UserService class depends on the ILogger interface, which is injected through a public property called Logger. The CreateUser method uses the injected ILogger to log a message during the user creation process.

In the Main method, we create an instance of UserService and an instance of ConsoleLogger. We then inject the ConsoleLogger into the UserService instance by assigning it to the Logger property. Finally, we call the CreateUser method on the userService instance, which uses the injected ILogger implementation to log a message.

Property injection is less commonly used than constructor injection because it makes dependencies optional (i.e., they can be null), and it can be harder to determine if a dependency has been properly injected or not. However, in some cases, it can be useful, especially when dealing with frameworks or situations where constructor injection is not possible or convenient.

3. Method injection:

Method injection is another approach to implementing dependency injection in C#. Instead of injecting dependencies through the constructor or properties, the dependencies are injected directly into specific methods of the dependent class. Here’s an example of method injection:

// Interface representing the dependency
public interface ICalculator
{
int Add(int a, int b);
}
// Concrete implementation of the dependency
public class BasicCalculator : ICalculator
{
public int Add(int a, int b)
{
return a + b;
}
}

// Class that depends on the ICalculator
public class CalculationService
{
public int PerformCalculation(int a, int b, ICalculator calculator)
{
return calculator.Add(a, b);
}
}

// Usage example
public class Program
{
public static void Main()
{
// Create an instance of the dependent class
CalculationService calculationService = new CalculationService();

// Create an instance of the dependency
ICalculator calculator = new BasicCalculator();

// Use the dependent class and inject the dependency into the method
int result = calculationService.PerformCalculation(5, 3, calculator);

Console.WriteLine($"Result: {result}"); // Output: Result: 8
}
}

In the example above, we have an ICalculator interface that defines the contract for a calculator. The BasicCalculator class implements this interface and provides concrete implementation for performing addition.

The CalculationService class depends on the ICalculator interface, which is injected into the PerformCalculation method as a parameter. The method uses the injected ICalculator to perform the addition and returns the result.

In the Main method, we create an instance of CalculationService and an instance of BasicCalculator. We then call the PerformCalculation method on the calculationService instance, passing in the BasicCalculator instance as the dependency. The method injection allows us to provide the necessary dependency only when it’s needed for a specific method call.

Method injection is useful in scenarios where a dependency is required for a specific method but not for the entire lifespan of the dependent object. It allows for more fine-grained control over when and where a dependency is injected, making the code more flexible and focused on specific operations.

This is a basic example, but it demonstrates the concept of dependency injection in C#. In practice, you would typically use a DI container like Autofac, Ninject, or the built-in .NET Core DI container to manage dependencies and automatically resolve them based on configuration or conventions.

Please Follow me on

Kamlesh Singh

If you enjoyed this article and would like to receive more content like this, please subscribe to my newsletter by clicking here. You’ll be the first to know when I publish new articles, and you can unsubscribe at any time.

--

--

Kamlesh Singh

Full Stack | Angular| .Net| .Net Core| SQL | Azure PaaS | Azure | AWS