如何保持(.NET Core)依赖注入配置可维护?

时间:2019-06-25 09:15:32

标签: c# dependency-injection .net-core

我在Microsoft.Extensions.DependencyInjection Dependency Injection中为.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;
        }        
    }

随着解决方案的发展,将会有更多的服务,例如50多个,并且每个服务都需要在Interface中为Implementation class注册其Startup.csDependency Injection。我需要知道有没有更好的方法来实现Dependency Injection,而无需在注册代码中手动添加新服务InterfaceImplementation class

2 个答案:

答案 0 :(得分:2)

Dependency Injection, Principles, Practices, and Patterns的第12章中,Mark Seemann和我描述了使用DI容器时有多个配置选项,即:

  • 配置文件 –在配置文件中指定映射(通常以XML或JSON格式)
  • Configuration as Code –代码明确确定映射
  • Auto-Registration –规则用于通过反射来定位合适的组件并构建映射。

您当前正在申请Configuration as Code。但是,对于Auto-Registration,您可以基于指定的约定应用 Convention over Configuration 通过反射注册您的应用程序组件。

在12.3节中,我们详细介绍了何时应该使用DI容器,以及如何应该使用它。总之,我们声明:

  

通过Auto-Registration使用约定优于配置可以将Composition Root的维护量减少到几乎为零。

因此,我们建议:

  

一个Composition Root应该要么集中在Pure DI上(可能有一些后期绑定类型),要么应该集中在Auto-Registration上,并选择有限的{{1} }和配置文件。围绕Configuration as Code的{​​{1}}是毫无意义的,因此应避免使用。

在本书的第6章和第10章中,我们还描述了可以使用的设计种类,其中包括最大程度地提高配置约定,并因此最大程度地减少DI配置的维护量。

答案 1 :(得分:0)

我已经通过向我的每个项目“ PluginConfiguration”中添加一个类来实现此目的,该类传递IServiceCollection,并在构造函数中注册其各个服务。然后,只需在我的主服务中调用ServicesCollection中的每个“ Plugin”即可项目。它将配置抽象为与单个项目相关的类,并为每个其他项目仅使用一行代码即可保持主配置整洁