一个项目中的依赖项注入可被解决方案中的其他项目使用

时间:2020-06-18 00:20:02

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

我有一个Visual Studio解决方案,其中包括多个项目(Hosts.Project1,Hosts.Project2):

enter image description here

每个项目解决方案中的启动类如下:

        public class Startup : FunctionsStartup
        {
          private IConfigurationRoot _configuration;
          public override void Configure(IFunctionsHostBuilder builder)
          {
            var serviceProvider = builder.Services.BuildServiceProvider();
            var configurationRoot = serviceProvider.GetService<IConfiguration>();
            var configurationBuilder = new ConfigurationBuilder();
            var azureServiceTokenProvider = new AzureServiceTokenProvider();
            var keyVaultClient = new KeyVaultClient(
                new KeyVaultClient.AuthenticationCallback(
                    azureServiceTokenProvider.KeyVaultTokenCallback));

            configurationBuilder.AddConfiguration(configurationRoot);
            configurationBuilder.AddAzureKeyVault($"https://{configurationRoot["keyVaultName"]}.vault.azure.net/", keyVaultClient, new DefaultKeyVaultSecretManager());

            _configuration = configurationBuilder.Build();
            builder.Services.Replace(ServiceDescriptor.Singleton(typeof(IConfiguration), _configuration));

            builder.Services.AddSingleton<IARepo, ARepo>();
            builder.Services.AddSingleton<IBRepo, BRepo>();
            builder.Services.AddSingleton<ILogRepo, LogRepo>();
        }
    }

每个项目解决方案都需要“ keyVaultName”,才能访问“ LogRepo”。每个启动类中只有以下部分有所不同:

 builder.Services.AddSingleton<IARepo, ARepo>();
 builder.Services.AddSingleton<IBRepo, BRepo>();

如何创建一个新的项目解决方案(Hosts.ProjectCommon),其中包括一个通用的启动类(带有keyVaultName,访问LogRepo的权限),我可以从其他项目解决方案中引用此通用的启动类并重用该通用的启动类和仅在单个项目解决方案中更新依赖项注入代码?

1 个答案:

答案 0 :(得分:1)

我假设您有一个Visual Studio解决方案,其中包含多个单独的应用程序项目,例如:

Solution
|__> Hosts.Project1 (requires <IARepo, A1Repo>)
|__> Hosts.Project2 (requires <IARepo, A2Repo>)

您可以利用继承将常见的配置调用提取到基类中,并覆盖对特定注册的调用。

您的解决方案看起来像这样

Solution
|__> Hosts.Project1 //(requires <IARepo, A1Repo>)
    |__> RegistratorApp1 : BaseRegistrator
|__> Hosts.Project2 //(requires <IARepo, A2Repo>)
    |__> RegistratorApp2 : BaseRegistrator
|__> Hosts.Base //(includes base configuration)
    |__> BaseRegistrator

这些单个类的实际代码可能看起来像这样:

(请注意,这3个类实际上位于不同的项目中。如上面的片段所示)

public class BaseRegistrator {
  public BaseRegistrator(){}
  private IConfigurationRoot _configuration;
  public void Register(IFunctionsHostBuilder builder)
  {
    var serviceProvider = builder.Services.BuildServiceProvider();
    var configurationRoot = serviceProvider.GetService<IConfiguration>();
    var configurationBuilder = new ConfigurationBuilder();
    var azureServiceTokenProvider = new AzureServiceTokenProvider();
    var keyVaultClient = new KeyVaultClient(
        new KeyVaultClient.AuthenticationCallback(
            azureServiceTokenProvider.KeyVaultTokenCallback));

    configurationBuilder.AddConfiguration(configurationRoot);
    configurationBuilder.AddAzureKeyVault($"https://{configurationRoot["keyVaultName"]}.vault.azure.net/", keyVaultClient, new DefaultKeyVaultSecretManager());

    _configuration = configurationBuilder.Build();
    builder.Services.Replace(ServiceDescriptor.Singleton(typeof(IConfiguration), _configuration));

    RegisterApplicationDependentServices(builder)

    builder.Services.AddSingleton<ILogRepo, LogRepo>();
  }

  protected virtual void RegisterApplicationDependentServices(IFunctionsHostBuilder builder){

  }
}

public class RegistratorApp1 : BaseRegistrator {
  public RegistratorApp1(){}

  protected override void RegisterApplicationDependentServices(IFunctionsHostBuilder builder){
    builder.Services.AddSingleton<IARepo, A1Repo>();
    builder.Services.AddSingleton<IBRepo, B1Repo>();
  }
}

public class RegistratorApp2 : BaseRegistrator {
  public RegistratorApp2(){}

  protected override void RegisterApplicationDependentServices(IFunctionsHostBuilder builder){
    builder.Services.AddSingleton<IARepo, A2Repo>();
    builder.Services.AddSingleton<IBRepo, B2Repo>();
  }
}

现在在您的各个启动类中,您只需创建RegistratorApp1或RegistratorApp2的新实例,然后调用基寄存器方法(依次调用重写的/特定的RegisterApplicationDependentServices实现)

//startup of Hosts.Project1
public class Startup : FunctionsStartup
{
  public override void Configure(IFunctionsHostBuilder builder)
  {
    var registrator = new RegistratorApp1();
    registrator.Register(builder);
  }
}