Zwykle w projekcie .NET Core stworzyłbym klasę „boostrap”, aby skonfigurować moją usługę wraz z poleceniami rejestracji DI. Zazwyczaj jest to metoda rozszerzenia, w IServiceCollection
której mogę wywołać metodę podobną .AddCosmosDbService
i wszystko, co niezbędne, jest „samodzielne” w klasie statycznej zawierającej tę metodę. Kluczem jest jednak, że metoda pobiera IConfiguration
z Startup
klasy.
Pracowałem z DI w Azure Functions w przeszłości, ale jeszcze nie spotkałem się z tym konkretnym wymaganiem.
Używam IConfiguration
do powiązania z konkretną klasą z właściwościami dopasowującymi ustawienia zarówno mojego, local.settings.json
jak i ustawień aplikacji deweloperskiej / produkcyjnej, gdy funkcja jest wdrażana na platformie Azure.
CosmosDbClientSettings.cs
/// <summary>
/// Holds configuration settings from local.settings.json or application configuration
/// </summary>
public class CosmosDbClientSettings
{
public string CosmosDbDatabaseName { get; set; }
public string CosmosDbCollectionName { get; set; }
public string CosmosDbAccount { get; set; }
public string CosmosDbKey { get; set; }
}
BootstrapCosmosDbClient.cs
public static class BootstrapCosmosDbClient
{
/// <summary>
/// Adds a singleton reference for the CosmosDbService with settings obtained by injecting IConfiguration
/// </summary>
/// <param name="services"></param>
/// <param name="configuration"></param>
/// <returns></returns>
public static async Task<CosmosDbService> AddCosmosDbServiceAsync(
this IServiceCollection services,
IConfiguration configuration)
{
CosmosDbClientSettings cosmosDbClientSettings = new CosmosDbClientSettings();
configuration.Bind(nameof(CosmosDbClientSettings), cosmosDbClientSettings);
CosmosClientBuilder clientBuilder = new CosmosClientBuilder(cosmosDbClientSettings.CosmosDbAccount, cosmosDbClientSettings.CosmosDbKey);
CosmosClient client = clientBuilder.WithConnectionModeDirect().Build();
CosmosDbService cosmosDbService = new CosmosDbService(client, cosmosDbClientSettings.CosmosDbDatabaseName, cosmosDbClientSettings.CosmosDbCollectionName);
DatabaseResponse database = await client.CreateDatabaseIfNotExistsAsync(cosmosDbClientSettings.CosmosDbDatabaseName);
await database.Database.CreateContainerIfNotExistsAsync(cosmosDbClientSettings.CosmosDbCollectionName, "/id");
services.AddSingleton<ICosmosDbService>(cosmosDbService);
return cosmosDbService;
}
}
Startup.cs
public class Startup : FunctionsStartup
{
public override async void Configure(IFunctionsHostBuilder builder)
{
builder.Services.AddHttpClient();
await builder.Services.AddCosmosDbServiceAsync(**need IConfiguration reference**); <--where do I get IConfiguration?
}
}
Oczywiście dodanie prywatnego pola dla IConfiguration
w Startup.cs
nie będzie działać, ponieważ musi być wypełnione czymś, a także przeczytałem, że używanie DI dla IConfiguration
nie jest dobrym pomysłem .
Próbowałem również użyć wzorca opcji, jak opisano tutaj i zaimplementowałem jako taki:
builder.Services.AddOptions<CosmosDbClientSettings>()
.Configure<IConfiguration>((settings, configuration) => configuration.Bind(settings));
Chociaż działałoby to w celu wstrzyknięcia IOptions<CosmosDbClientSettings>
do klasy niestatycznej, używam klasy statycznej do wstrzymania mojej pracy konfiguracyjnej.
Wszelkie sugestie na temat tego, jak mogę to zrobić lub możliwe obejście? Wolałbym zachować całą konfigurację w jednym miejscu (plik bootstrap).
host.json
parametry nie są używane, w szczególnościroutePrefix