C# 瞬态ASP.NET内核的异步初始化
我有一个临时服务,它必须进行异步初始化(连接到不同的服务器)。 它公开了一个属性C# 瞬态ASP.NET内核的异步初始化,c#,asp.net-core,dependency-injection,async-await,C#,Asp.net Core,Dependency Injection,Async Await,我有一个临时服务,它必须进行异步初始化(连接到不同的服务器)。 它公开了一个属性public Task InitTask,用户可以等待该属性直到服务初始化。 它还公开了在InitTask完成后可以保存访问的子服务 public class Service { public Task InitTask { get; } public ISubService1 SubService1 { get; } public ISubService2 SubService2 { ge
public Task InitTask
,用户可以等待该属性直到服务初始化。
它还公开了在InitTask
完成后可以保存访问的子服务
public class Service
{
public Task InitTask { get; }
public ISubService1 SubService1 { get; }
public ISubService2 SubService2 { get; }
public ISubService3 SubService3 { get; }
}
连接到其他服务器所提供的所有功能都由这些子服务控制。
通常我会注入主服务,然后等待它完成初始化,然后使用其中一个子服务。
但我只想注入这些子服务
起初我试过了
services.AddTransient<Service>()
.AddTransient(provider =>
{
var server = provider.GetService<Service>();
return server.SubService1;
})
.AddTransient(provider =>
{
var server = provider.GetService<Service>();
return server.SubService2;
})
.AddTransient(provider =>
{
var server = provider.GetService<Service>();
return server.SubService3;
});
在启动时做什么
services.AddTransient<Service>()
.AddTransient<ISubService1, WrapperSubService1>()
.AddTransient<ISubService2, WrapperSubService2>()
.AddTransient<ISubService3, WrapperSubService3>();
services.AddTransient()
.AddTransient()
.AddTransient()
.AddTransient();
但这也有一个明显的缺陷:代码重复
我希望的是:
services.AddTransient<Service>()
.AddTransient(async provider =>
{
var server = provider.GetService<Service>();
await server.InitTask;
return server.SubService1;
})
.AddTransient(async provider =>
{
var server = provider.GetService<Service>();
await server.InitTask;
return server.SubService2;
})
.AddTransient(async provider =>
{
var server = provider.GetService<Service>();
await server.InitTask;
return server.SubService3;
});
services.AddTransient()
.AddTransient(异步提供程序=>
{
var server=provider.GetService();
等待server.InitTask;
返回server.SubService1;
})
.AddTransient(异步提供程序=>
{
var server=provider.GetService();
等待server.InitTask;
返回server.SubService2;
})
.AddTransient(异步提供程序=>
{
var server=provider.GetService();
等待server.InitTask;
返回server.SubService3;
});
但这只会公开任务
以供注入
有什么想法吗?我认为在这种情况下,您实际上可以使用显式接口实现: 将服务类更改为
公共类服务:ISubService1、ISubService2、ISubService3
{
公共任务初始化任务{get;}
公共ISubService1子服务1{get;}
公共ISubService2子服务2{get;}
公共ISubService3子服务3{get;}
....
专用异步值任务GetSubService1Async()
{
等待server.InitTask
返回server.SubService1;
}
//接口实现
异步任务ISubService1.GetExampleAncy(…)
{
var subService1=等待这个。GetSubService1Async();
return wait subService1.getExampleAscync(…);
}
....
异步任务ISubService2.getExampleAync(…)
{
var subService1=wait this.GetSubService2Async();
return wait subService1.getExampleAscync(…);
}
//等等
}
对于这种情况,我找到的唯一解决方案是:
我确实认为公开
任务
很好
至于解析服务的代码,它看起来像:
var subService1 = await serviceProvider.GetService<Task<SubService1>>();
var result = await subService1.GetExampleAsync();
var subService1=await serviceProvider.GetService();
var result=await subService1.getExampleAync();
它看起来很优雅。或者您可以编写一个扩展方法,如:
public static Task<T> GetServiceAsync<T>(this IServiceProvider provider) => provider.GetService<Task<T>>();
公共静态任务GetServiceAsync(此IServiceProvider提供程序)=>provider.GetService();
然后
var subService1=等待serviceProvider.GetServiceAsync();
会更清楚
此外,基于Microsoft.Extensions.DependencyInjection
的默认DI的设计不像对象容器,而只是一个IoC接口(这与众所周知的DI容器(如autofac)不同)。我们不应该直接从提供者检索每个对象,即使它看起来更优雅
因此,直接从主服务获取子服务
subService1=provider.GetService().GetService1Async()代码>将是推荐的方式。相关:相关:相关:为什么子服务定义为服务的属性?如果它们可以单独使用,但依赖于服务
,那么为什么不将服务
注入到您的子服务中呢?
public static Task<T> GetServiceAsync<T>(this IServiceProvider provider) => provider.GetService<Task<T>>();
var subService1 = await serviceProvider.GetServiceAsync<SubService1>();