Normalement, dans un projet .NET Core, je créais une classe «boostrap» pour configurer mon service avec les commandes d'enregistrement DI. C'est généralement une méthode d'extension d' IServiceCollection
où je peux appeler une méthode comme .AddCosmosDbService
et tout ce qui est nécessaire est «autonome» dans la classe statique contenant cette méthode. La clé est que la méthode obtient un IConfiguration
de la Startup
classe.
J'ai déjà travaillé avec DI dans Azure Functions, mais je n'ai pas encore rencontré cette exigence spécifique.
J'utilise le IConfiguration
pour lier à une classe concrète avec des propriétés correspondant aux paramètres de mon local.settings.json
ainsi qu'aux paramètres de l'application de développement / production lorsque la fonction est déployée dans 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?
}
}
Évidemment, l'ajout d'un champ privé pour IConfiguration
in Startup.cs
ne fonctionnera pas car il doit être rempli avec quelque chose et j'ai également lu que l' utilisation de DI for IConfiguration
n'est pas une bonne idée .
J'ai également essayé d'utiliser le modèle d'options décrit ici et mis en œuvre en tant que tel:
builder.Services.AddOptions<CosmosDbClientSettings>()
.Configure<IConfiguration>((settings, configuration) => configuration.Bind(settings));
Bien que cela fonctionne pour injecter un IOptions<CosmosDbClientSettings>
dans une classe non statique, j'utilise une classe statique pour conserver mon travail de configuration.
Des suggestions sur la façon dont je peux faire ce travail ou une solution possible? Je préfère garder toute la configuration en un seul endroit (fichier bootstrap).
host.json
paramètres ne sont pas utilisés, en particulier,routePrefix