3355307
3355307

Reputation: 1678

How can I keep my (.NET Core) Dependency Injection configuration maintainable?

I am using Microsoft.Extensions.DependencyInjection for Dependency Injection in .NET Core Console Application.

 public class Program
    {
        public IConfiguration Configuration { get; }
        public static void Main(string[] args)
        {
            IServiceCollection services = new ServiceCollection();
            Startup startup = new Startup();
            startup.ConfigureServices(services);

            IServiceProvider serviceProvider = services.BuildServiceProvider();
            var etlService = serviceProvider.GetService<IETLService>();              
        }
    }

 public class Startup
    {
        IConfigurationRoot Configuration { get; }

        public Startup()
        {
            var builder = new ConfigurationBuilder()
                .AddJsonFile("appsettings.json");
                Configuration = builder.Build();
        }

        public void ConfigureServices(IServiceCollection services)
    {
        var sqlServerConnectionString = Configuration.GetConnectionString("SqlServerConnection");

        services.AddDbContext<ETLSqlContext>(options =>
            options.UseSqlServer(sqlServerConnectionString), ServiceLifetime.Scoped);

        services.AddSingleton(Configuration);
        services.AddTransient<ISqlRepository, SqlRepository>();
        services.AddTransient<IAzureSqlRepository, AzureSqlRepository>();
        services.AddTransient<IExtractService, ExtractService>();
        services.AddTransient<ILoadService, LoadService>();
    }
 }

 public class ExtractService : IExtractService
    {
        public ISqlRepository SqlRepository { get; set; }
        public IAzureSqlRepository AzureSqlRepository { get; set; }
        public ExtractService(ISqlRepository sqlRepository, IAzureSqlRepository azureSqlRepository)
        {
            SqlRepository = sqlRepository;
            AzureSqlRepository = azureSqlRepository;
        }        
    }

As solution grows there will be more services for example 50+ and each service will require registering its Interface and Implementation class in Startup.cs for Dependency Injection. I need to know is there any better way to implement Dependency Injection which does not require manually adding new service Interface and Implementation class in registration code

Upvotes: 1

Views: 698

Answers (2)

Steven
Steven

Reputation: 172646

In chapter 12 of Dependency Injection, Principles, Practices, and Patterns, Mark Seemann and I describe that there are multiple configuration options when working with a DI Container, namely:

  • Configuration files–Mapping are specified in configuration files (typically in XML or JSON format)
  • Configuration as Code–Code explicitly determines mappings
  • Auto-Registration–Rules are used to locate suitable components using reflection and to build the mappings.

You are currently applying Configuration as Code. With Auto-Registration, however, you apply Convention over Configuration to register your application components using reflection, based on a specified convention.

In section 12.3 we describe in detail when you should use a DI Container, and how you should use it. In summary we state that:

The use of Convention over Configuration using Auto-Registration can minimize the amount of maintenance on the Composition Root to almost zero.

We, therefore, advice:

a Composition Root should either be focused around Pure DI with, perhaps a few late-bound types, or around Auto-Registration with, optionally, a limited amount of Configuration as Code and configuration files. A Composition Root that focuses around Configuration as Code is pointless and should therefore be avoided.

In chapters 6 and 10 of the book, we also describe the kinds of designs you can use that, among other things, maximize convention over configuration and, with it, minimizes the amount of maintenance on your DI configuration.

Upvotes: 2

Robert Perry
Robert Perry

Reputation: 1956

I've done this by adding a class to each of my projects "PluginConfiguration", which passes in the IServiceCollection, and registers its individual services in the constructor.. Then just call each "Plugin" in the ServicesCollection in my main project. It abstracts out the config into a class thats relevant to the individual project and keeps the main config clean with just a single line of code for each additional project

Upvotes: 0

Related Questions