Normalmente in un progetto .NET Core avrei creato una classe 'boostrap' per configurare il mio servizio insieme ai comandi di registrazione DI. Questo è di solito un metodo di estensione in IServiceCollection
cui posso chiamare un metodo simile .AddCosmosDbService
e tutto il necessario è "autonomo" nella classe statica contenente quel metodo. La chiave però è che il metodo ottiene un IConfiguration
dalStartup
classe.
Ho lavorato con DI in Funzioni di Azure in passato ma non ho ancora incontrato questo requisito specifico.
Sto usando il IConfiguration
per legare a una classe concreta con proprietà che corrispondono alle impostazioni di entrambi i mieilocal.settings.json
che delle impostazioni di sviluppo / produzione dell'applicazione quando la funzione viene distribuita in 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?
}
}
Ovviamente aggiungere un campo privato per IConfiguration
in Startup.cs
non funzionerà in quanto deve essere popolato con qualcosa e ho anche letto che usare DI per IConfiguration
non è una buona idea .
Ho anche provato a utilizzare il modello di opzioni come descritto qui e implementato come tale:
builder.Services.AddOptions<CosmosDbClientSettings>()
.Configure<IConfiguration>((settings, configuration) => configuration.Bind(settings));
Mentre questo funzionerebbe per iniettare una IOptions<CosmosDbClientSettings>
classe non statica, sto usando una classe statica per conservare il mio lavoro di configurazione.
Qualche suggerimento su come posso farlo funzionare o una possibile soluzione? Preferirei mantenere tutta la configurazione in un unico posto (file bootstrap).
host.json
parametri non vengono utilizzati, in particolare,routePrefix