Normalmente en un proyecto .NET Core, crearía una clase 'boostrap' para configurar mi servicio junto con los comandos de registro DI. Este suele ser un método de extensión de IServiceCollection
donde puedo llamar a un método como .AddCosmosDbService
y todo lo necesario es 'autocontenido' en la clase estática que contiene ese método. Sin embargo, la clave es que el método obtiene un IConfiguration
de la Startup
clase.
He trabajado con DI en Azure Functions en el pasado, pero todavía no me he encontrado con este requisito específico.
Estoy usando el IConfiguration
enlace para una clase concreta con propiedades que coinciden con la configuración de mi local.settings.json
y la configuración de la aplicación de desarrollo / producción cuando la función se implementa en 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?
}
}
Obviamente, agregar un campo privado para IConfiguration
in Startup.cs
no funcionará, ya que debe rellenarse con algo y también he leído que usar DI para IConfiguration
no es una buena idea .
También intenté usar el patrón de opciones como se describe aquí y lo implementé como tal:
builder.Services.AddOptions<CosmosDbClientSettings>()
.Configure<IConfiguration>((settings, configuration) => configuration.Bind(settings));
Si bien esto funcionaría para inyectar una IOptions<CosmosDbClientSettings>
clase no estática, estoy usando una clase estática para mantener mi trabajo de configuración.
¿Alguna sugerencia sobre cómo puedo hacer que esto funcione o una posible solución? Prefiero mantener toda la configuración en un solo lugar (archivo de arranque).
host.json
parámetros no se utilizan, en particular,routePrefix