Normalerweise würde ich in einem .NET Core-Projekt eine 'Boostrap'-Klasse erstellen, um meinen Dienst zusammen mit den DI-Registrierungsbefehlen zu konfigurieren. Dies ist normalerweise eine Erweiterungsmethode, IServiceCollection
bei der ich eine Methode wie aufrufen kann .AddCosmosDbService
und alles Notwendige in der statischen Klasse, die diese Methode enthält, in sich geschlossen ist. Der Schlüssel ist jedoch, dass die Methode eine IConfiguration
von der Startup
Klasse erhält .
Ich habe in der Vergangenheit in Azure-Funktionen mit DI gearbeitet, bin jedoch noch nicht auf diese spezielle Anforderung gestoßen.
Ich verwende die IConfiguration
Option zum Binden an eine konkrete Klasse mit Eigenschaften, die den Einstellungen sowohl meiner local.settings.json
als auch der Entwicklungs- / Produktionsanwendungseinstellungen entsprechen, wenn die Funktion in Azure bereitgestellt wird.
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?
}
}
Offensichtlich funktioniert das Hinzufügen eines privaten Felds für IConfiguration
in Startup.cs
nicht, da es mit etwas gefüllt werden muss, und ich habe auch gelesen, dass die Verwendung von DI für IConfiguration
keine gute Idee ist .
Ich habe auch versucht, das hier beschriebene und als solches implementierte Optionsmuster zu verwenden :
builder.Services.AddOptions<CosmosDbClientSettings>()
.Configure<IConfiguration>((settings, configuration) => configuration.Bind(settings));
Während dies funktionieren würde, um IOptions<CosmosDbClientSettings>
eine nicht statische Klasse zu injizieren , verwende ich eine statische Klasse, um meine Konfigurationsarbeit zu speichern.
Irgendwelche Vorschläge, wie ich diese Arbeit machen kann oder eine mögliche Problemumgehung? Ich würde es vorziehen, die gesamte Konfiguration an einem Ort zu speichern (Bootstrap-Datei).
host.json
insbesondere keine Parameter verwendet werdenroutePrefix