How to inject or use IConfiguration in Azure Function V3 with Dependency Injection when configuring a service

前端 未结 4 1883
挽巷
挽巷 2021-02-02 12:46

Normally in a .NET Core project I would create a \'boostrap\' class to configure my service along with the DI registration commands. This is usually an extension method of

4条回答
  •  余生分开走
    2021-02-02 13:02

    The linked example is poorly designed (In My Opinion). It encourages tight coupling and the mixing of async-await and blocking calls.

    IConfiguration is added to the service collection by default as part of the start up, so I would suggest changing up your design to take advantage of the deferred resolution of dependencies so that the IConfiguration can be resolved via the built IServiceProvider using a factory delegate.

    public static class BootstrapCosmosDbClient {
    
        private static event EventHandler initializeDatabase = delegate { };
    
        public static IServiceCollection AddCosmosDbService(this IServiceCollection services) {
    
            Func factory = (sp) => {
                //resolve configuration
                IConfiguration configuration = sp.GetService();
                //and get the configured settings (Microsoft.Extensions.Configuration.Binder.dll)
                CosmosDbClientSettings cosmosDbClientSettings = configuration.Get();
                string databaseName = cosmosDbClientSettings.CosmosDbDatabaseName;
                string containerName = cosmosDbClientSettings.CosmosDbCollectionName;
                string account = cosmosDbClientSettings.CosmosDbAccount;
                string key = cosmosDbClientSettings.CosmosDbKey;
    
                CosmosClientBuilder clientBuilder = new CosmosClientBuilder(account, key);
                CosmosClient client = clientBuilder.WithConnectionModeDirect().Build();
                CosmosDbService cosmosDbService = new CosmosDbService(client, databaseName, containerName);
    
                //async event handler
                EventHandler handler = null;
                handler = async (sender, args) => {
                    initializeDatabase -= handler; //unsubscribe
                    DatabaseResponse database = await client.CreateDatabaseIfNotExistsAsync(databaseName);
                    await database.Database.CreateContainerIfNotExistsAsync(containerName, "/id");
                };
                initializeDatabase += handler; //subscribe
                initializeDatabase(null, EventArgs.Empty); //raise the event to initialize db
    
                return cosmosDbService;
            };
            services.AddSingleton(factory);
            return service;
        }
    }
    

    Note the approach taken to get around the having to use async void in a non-async event handler.

    Reference Async/Await - Best Practices in Asynchronous Programming.

    So now the Configure can be properly invoked.

    public class Startup : FunctionsStartup {
    
        public override void Configure(IFunctionsHostBuilder builder) =>
            builder.Services
                .AddHttpClient()
                .AddCosmosDbService();
    }
    

提交回复
热议问题