Внедрение зависимостей в проект, который может использоваться другими проектами в решении - PullRequest
0 голосов
/ 18 июня 2020

У меня есть решение 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 Ответ

1 голос
/ 18 июня 2020

Я предполагаю, что у вас есть одно решение Visual Studio с несколькими отдельными проектами приложений, например:

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

Вы можете использовать наследование, чтобы извлечь общие вызовы конфигурации в базовый класс и переопределить вызовы для указанных c регистрация.

Ваше решение будет выглядеть так

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 и вызвать метод базового регистра (который, в свою очередь, вызывает реализацию overridden / specific c RegisterApplicationDependentServices)

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