일반적으로 .NET Core 프로젝트에서 DI 등록 명령과 함께 내 서비스를 구성하기 위해 '부 스트랩'클래스를 만듭니다. 이것은 일반적으로 같은 메서드를 IServiceCollection
호출 할 수 있는 확장 메서드이며 .AddCosmosDbService
필요한 모든 것은 해당 메서드를 포함하는 정적 클래스에서 '자체 포함'됩니다. 그러나 핵심은 메서드가 클래스 IConfiguration
에서 가져 오는 것 입니다 Startup
.
과거에 Azure Functions에서 DI로 작업했지만 아직이 특정 요구 사항을 만나지 못했습니다.
내가 사용하고 IConfiguration
속성 모두에서 설정 내 일치하는 구체적인 클래스에 바인딩하는 local.settings.json
기능이 푸른에 배포 할 때뿐만 아니라 dev에 / 생산 응용 프로그램 설정을.
/// <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; }
}
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;
}
}
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?
}
}
분명히 IConfiguration
in에 대한 비공개 필드를 추가하는 것은 Startup.cs
무언가로 채워 져야하기 때문에 작동하지 않으며 DI를 사용 IConfiguration
하는 것이 좋은 생각이 아니라는 것도 읽었습니다 .
또한 여기에 설명 된대로 옵션 패턴을 사용해 보았고 다음 과 같이 구현했습니다.
builder.Services.AddOptions<CosmosDbClientSettings>()
.Configure<IConfiguration>((settings, configuration) => configuration.Bind(settings));
이것은 IOptions<CosmosDbClientSettings>
비 정적 클래스 에 주입하는 데 작동하지만 정적 클래스를 사용하여 구성 작업을 유지하고 있습니다.
이 작업을 수행하거나 가능한 해결 방법에 대한 제안 사항이 있습니까? 모든 구성을 한곳 (부트 스트랩 파일)에 보관하고 싶습니다.
링크 된 예는 제대로 (제 생각에) 설계되었습니다. 긴밀한 결합과 비동기 대기 및 차단 호출의 혼합을 장려합니다.
IConfiguration
기본적으로 시작의 일부로 서비스 컬렉션에 추가되므로 팩토리 위임을 사용 IConfiguration
하여 빌드 IServiceProvider
를 통해 해결할 수 있도록 지연된 종속성 확인을 활용하도록 디자인을 변경하는 것이 좋습니다 .
public static class BootstrapCosmosDbClient {
private static event EventHandler initializeDatabase = delegate { };
public static IServiceCollection AddCosmosDbService(this IServiceCollection services) {
Func<IServiceProvider, ICosmosDbService> factory = (sp) => {
//resolve configuration
IConfiguration configuration = sp.GetService<IConfiguration>();
//and get the configured settings (Microsoft.Extensions.Configuration.Binder.dll)
CosmosDbClientSettings cosmosDbClientSettings = configuration.Get<CosmosDbClientSettings>();
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<ICosmosDbService>(factory);
return service;
}
}
async void
비동기 이벤트 핸들러에서 사용해야하는 문제를 해결하기 위해 취한 접근 방식에 유의하십시오 .
참조 Async / Await-비동기 프로그래밍의 모범 사례 .
이제를 Configure
제대로 호출 할 수 있습니다.
public class Startup : FunctionsStartup {
public override void Configure(IFunctionsHostBuilder builder) =>
builder.Services
.AddHttpClient()
.AddCosmosDbService();
}
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다