使用 ServiceProvider 将 IServiceProvider 注入 SignInManager

Ale*_*nko 5 c# dependency-injection asp.net-core

我做了一些研究,并且没有太多关于注册手动 DI 标准类的信息。尝试在 asp net core 2.1 应用程序中实现单元测试时遇到很多问题,这是最后一个。尝试 UserManager 创建的 SignInAsync 用户时出现空引用异常 - 似乎无法注入 IServiceProvider 实例

var userManager = Resolve<UserManager<ApplicationUser>>();
await signInManager.SignInAsync(userManager.FindByIdAsync(adminId), false); // here
Run Code Online (Sandbox Code Playgroud)

值不能为空。参数名称:提供程序位于 Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider 提供程序),位于 Microsoft.AspNetCore.Identity.SignInManager 1.SignInAsync(TUser user, AuthenticationProperties authenticationProperties, String authenticationMethod) at UnitTests.TestBase1.ConfigureIdentity() in C:\Users\alexa\source\repos\octopusstore\UnitTests\ TestBase.cs:第 72 行

像这样解决

protected static ServiceCollection services = new ServiceCollection();
protected T Resolve<T>()
{
    var serviceProvider = services.BuildServiceProvider();
    return serviceProvider.GetRequiredService<T>();
}
Run Code Online (Sandbox Code Playgroud)

我如何注册依赖项,到目前为止它有效

services.AddDbContext<AppIdentityDbContext>();
var conf = new Mock<IConfiguration>();
services.AddSingleton<IConfiguration>(conf.Object);
services.AddSingleton<IServiceProvider, ServiceProvider>() ; // except for this
services.AddSingleton(services.BuildServiceProvider()); // and this
services.AddScoped<SignInManager<ApplicationUser>> ();
services.AddIdentity<ApplicationUser, IdentityRole>()
       .AddEntityFrameworkStores<AppIdentityDbContext>()
       .AddDefaultTokenProviders();
services.AddScoped<IAuthorizationService, DefaultAuthorizationService> ();
services.AddScoped<IAuthorizationPolicyProvider, DefaultAuthorizationPolicyProvider>();
services.AddScoped<IAuthorizationHandlerProvider, DefaultAuthorizationHandlerProvider>();
services.AddScoped<IAuthorizationHandlerContextFactory, DefaultAuthorizationHandlerContextFactory>();
services.AddScoped<IAuthorizationEvaluator, DefaultAuthorizationEvaluator>();       
Run Code Online (Sandbox Code Playgroud)

有趣的是 UserManager 工作得很好

pok*_*oke 10

要注册服务提供商本身,您可以这样做:

services.AddSingleton<IServiceProvider>(sp => sp);
Run Code Online (Sandbox Code Playgroud)

这使用了工厂函数,您可以使用该函数通过服务提供者获取实例sp。由于你要注册服务商本身,所以直接返回即可sp