Wednesday, 11 September 2024

Keyed Dependency Injection for Services in.NET

Leave a Comment

Dependency Injection (DI) is a potent pattern in.NET that facilitates unit testing, enhances code modularity, and manages dependencies between components. Sometimes, though, you have to deal with several implementations of the same interface or service. Keyed Service Dependency Injection is useful in this situation.



With Keyed Service DI, you can register several services with the same interface, each identified by a different key, and then resolve the services using that key. When you wish to manage which of multiple implementations of the same interface is injected at runtime, this method works well.

This post will explore the features, advantages, and real-world use of Keyed Service DI in.NET.

By using Keyed Service DI, you can achieve,

  1. Cleaner Code: Avoids cluttering the business logic with conditional statements.
  2. Decoupling: Keeps implementations independent, making them easier to maintain and test.
  3. Flexibility: Offers runtime flexibility to decide which implementation to use based on application logic or configuration.
Implementing Keyed Service DI in .NET

Step 1. Open Visual Studio.

  • Open Visual Studio.
  • Click on "Create a new project".

Step 2. Create a New .NET Core Console Application.

  1. In the "Create a new project" window, search for "Console App" and select "Console App (.NET Core)".
  2. Click Next.
  3. Set the project name (e.g., KeyedServiceDemo).
  4. Choose a location to save the project and click Create.

Step 3. Install Required NuGet Packages (Optional).

If you're working with a web application, you may need additional packages like ASP.NET Core. But for this console app, we’ll stick with the default libraries.

  1. Right-click on the Solution in the Solution Explorer.
  2. Select Manage NuGet Packages.
  3. Search for Microsoft.Extensions.DependencyInjection (should be installed by default in .NET Core projects).
  4. Install it if necessary.

Step 4. Create the Interface.

  1. In Solution Explorer, right-click on the project.
  2. Select Add > New Folder and name it "Services".
  3. Right-click on the Services folder, then select Add > Class.
  4. Name the class IOperationService.cs and click Add.

Inside IOperationService.cs, add.

public interface IOperationService
{
    string PerformOperation();
}

Step 5. Implement the Services.

Now, you need to create two classes that implement the IOperationService.

5.1. Create AdditionService.

  1. Right-click on the Services folder.
  2. Select Add > Class and name it AdditionService.cs.
  3. Add the following code.
public class AdditionService : IOperationService
{
    public string PerformOperation()
    {
        return "Performing Addition Operation";
    }
}

5.2. Create SubtractionService.

  1. Right-click on the Services folder again.
  2. Select Add > Class and name it SubtractionService.cs.
  3. Add the following code.
public class SubtractionService : IOperationService { public string PerformOperation() { return "Performing Subtraction Operation"; } }
 

Step 6.
Create Enum for Keys.
  1. Right-click on the Services folder.
  2. Select Add > Class and name it OperationType.cs.
  3. Add the following code.
public enum OperationType
{
    Addition,
    Subtraction
}

Step 7. Create the Factory.

  1. Right-click on the Services folder.
  2. Select Add > Class and name it OperationServiceFactory.cs.
  3. Add the following code.
public interface IOperationServiceFactory
{
    IOperationService GetService(OperationType operationType);
}

public class OperationServiceFactory : IOperationServiceFactory
{
    private readonly IServiceProvider _serviceProvider;
    private readonly IDictionary<OperationType, Type> _serviceMapping;

    public OperationServiceFactory(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
        _serviceMapping = new Dictionary<OperationType, Type>
        {
            { OperationType.Addition, typeof(AdditionService) },
            { OperationType.Subtraction, typeof(SubtractionService) }
        };
    }

    public IOperationService GetService(OperationType operationType)
    {
        var serviceType = _serviceMapping[operationType];
        return (IOperationService)_serviceProvider.GetRequiredService(serviceType);
    }
}

Step 8. Register Services in Program.cs.

  1. Open Program.cs from Solution Explorer.
  2. Replace the default code with the following.
using Microsoft.Extensions.DependencyInjection;
using System;

namespace KeyedServiceDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            // Setup Dependency Injection
            var serviceProvider = new ServiceCollection()
                .AddTransient<AdditionService>()
                .AddTransient<SubtractionService>()
                .AddSingleton<IOperationServiceFactory, OperationServiceFactory>()
                .BuildServiceProvider();

            // Resolve Calculator and Execute Operation
            var calculator = new Calculator(serviceProvider.GetRequiredService<IOperationServiceFactory>());
            calculator.ExecuteOperation(OperationType.Addition);
            calculator.ExecuteOperation(OperationType.Subtraction);
        }
    }

    public class Calculator
    {
        private readonly IOperationServiceFactory _operationServiceFactory;

        public Calculator(IOperationServiceFactory operationServiceFactory)
        {
            _operationServiceFactory = operationServiceFactory;
        }

        public void ExecuteOperation(OperationType operationType)
        {
            var service = _operationServiceFactory.GetService(operationType);
            Console.WriteLine(service.PerformOperation());
        }
    }
}

Step 9. Build and Run the Application.

  1. Save all files.
  2. Press Ctrl+Shift+B to build the solution, or click Build > Build Solution.
  3. After building, press F5 to run the application or click the Start button.

Expected Output

You should see the following output in the Console Window.


Benefits of Keyed Service DI
  1. Simplifies Logic: Keyed DI reduces the need for if or switch statements to determine which service to use. Instead, it encapsulates this logic in the DI container.
  2. Improves Maintainability: By having different service implementations registered by key, it becomes easier to maintain and extend the application. You can add more services without modifying the core business logic.
  3. Runtime Flexibility: This approach allows for greater flexibility at runtime. Based on user inputs, configurations, or external conditions, the appropriate service implementation can be resolved dynamically.
  4. Better Testing: It’s easier to test different implementations without coupling the test logic to specific conditions or requiring complex mocking.
Real-World Use Cases

Here are some real-world use cases where Keyed Service DI can make a big difference.

  • Notification Systems: Different notification channels like Email, SMS, or Push notifications can be keyed and injected as needed.
  • Payment Gateways: Multiple payment processors (e.g., PayPal, Stripe) could be registered as different services and resolved dynamically.
  • Data Providers: You may want to switch between different data providers (e.g., SQL, NoSQL) depending on the context, environment, or user preferences.
Conclusion
Dependency on Keyed Services .NET's powerful injection mechanism provides scalability and flexibility, particularly when handling several service implementations for the same interface. It guarantees more readable and maintainable code and improves runtime flexibility.

Developers can improve the separation of concerns, prevent crowded code, and create more dynamic and testable apps by utilizing this strategy. Thus, to simplify your approach the next time you find yourself in need of numerous implementations of the same service, think about utilizing Keyed Service DI.

ASP.NET Core 9.0 Hosting Recommendation

One of the most important things when choosing a good ASP.NET Core 9.0 hosting is the feature and reliability. HostForLIFE is the leading provider of Windows hosting and affordable ASP.NET Core, their servers are optimized for PHP web applications. The performance and the uptime of the hosting service are excellent and the features of the web hosting plan are even greater than what many hosting providers ask you to pay for. 

At HostForLIFE.eu, customers can also experience fast ASP.NET Core hosting. The company invested a lot of money to ensure the best and fastest performance of the datacenters, servers, network and other facilities. Its datacenters are equipped with the top equipments like cooling system, fire detection, high speed Internet connection, and so on. That is why HostForLIFEASP.NET guarantees 99.9% uptime for ASP.NET Core. And the engineers do regular maintenance and monitoring works to assure its Orchard hosting are security and always up.

 

0 comments:

Post a Comment