Open Generics in ASPNET Core Dependency Injection -Part1

In this article, I will show you how to implement Open Generic Constructor Injection in .NET core to make the software Extensible and Maintainable. Let’s assume you want to implement an Audit system in your application, and currently, you are logging Audit info to the console.

To understand the problem, I have created a simple application in .net core that implements an audit log system without open generic.Below is the complete source code.

Main.cs

void Main()
{

	var container = Startup.Configure();
	var customerService = container.GetService<ICustomerService>();
	var fooService = container.GetService<FooService>();
	fooService.DoSomething();
	customerService.Get(1);

}

Startup.cs

public class Startup
{
	public static ServiceProvider Configure()
	{
		var provider = new ServiceCollection()
			.AddSingleton<ICustomerService, CustomerService>()
			.AddScoped<IAuditLog<CustomerService>, ConsoleAuditLog<CustomerService>>()
			.AddLogging(fs => fs.AddConsole())
			.BuildServiceProvider(validateScopes: false);
		return provider;
	}

}

Customer.cs

public class Customer
{
	public int Id { get; set; }
	public int Age { get; set; }
	public string Email { get; set; }
}

ICustomerService.cs

public interface ICustomerService
{
	Customer Get(int id);

}

CustomerService

public class CustomerService : ICustomerService
{

	private readonly IAuditLog<CustomerService> _auditManager;
	public CustomerService(IAuditLog<CustomerService> auditManager)
	{
		_auditManager = auditManager;

	}
	public Customer Get(int id)
	{
		// TODO: simulate getting customer from the database.
		var customer = new Customer() { Id = 1, Email = "john@doe.com", Age = 21 };
		_auditManager.Log("GET");
		return customer;
	}
}
public interface IAuditLog<T>
{
	void Log(string action);
}
public class ConsoleAuditLog<T> : IAuditLog<T>
{
	public string SourceName { get; }
	public ConsoleAuditLog()
	{
		SourceName = typeof(T).Name;
	}
	public void Log(string action)
	{
		Console.WriteLine($"{SourceName}- Logging {action} to Console");
	}
}

If you run the application, you will get the following output

CustomerService- Logging GET to Console

What is the problem with the current implementations?

After some time, you added more service to your project, then you have to register all the dependency into the DI container. For example, I am adding FooService and BarService.

public static ServiceProvider Configure()
	{
		var provider = new ServiceCollection()
			.AddSingleton<ICustomerService, CustomerService>()
			.AddSingleton<FooService>()
+			.AddScoped<IAuditLog<CustomerService>, ConsoleAuditLog<CustomerService>>()
+			.AddScoped<IAuditLog<FooService>, ConsoleAuditLog<FooService>>()
+           .AddScoped<IAuditLog<BarService>, ConsoleAuditLog<FooService>>()
			.AddLogging(fs => fs.AddConsole())
			.BuildServiceProvider(validateScopes: false);
		return provider;
	}

We can improve this solution by using Open Generic Constructor Injection which .net core provides out of the box. In part II, I will show you how to implement Open Generic to avoid registering the services in a container.

Open Generics in ASPNET Core Dependency Injection With Real World Example-Part2

Please do not post any spam link in the comment box😊

Post a Comment (0)
Previous Post Next Post