![](/img/trans.png)
[英]ASP.NET Core Dependency Injection: The Difference Between Factory and Instance?
[英]ASP.Net Core 3.0 Dependency Injection ignoring Factory Methods?
我最近迁移到 ASP.NET Core 3.0 并在启动时面临 DI 问题......他们在 ASP.NET Core 2.2 上运行良好。 如果我在 ASP.NET CORE 3.0 中使用旧的 WebHostBuilder,那么我看不到问题。 不确定问题是否特定于 Program.cs 中的新 HostBuilder 或 DI 在 3.0 中已更改。
程序.cs
public class Program
{
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
}
我有如下的UniqueRowKeyUserStore class。 构造函数采用 4 个接口。
public class UniqueRowKeyUserStore : UserStore<UniqueRowKeyUser>
{
public UniqueRowKeyUserStore(IStoreMetadata storeMetadata, ILookupNormalizer dataNormalizer, IDataProtector dataProtector, ILookupSplitter<StorablePartitionRowKeys> defaultMerger) : base(storeMetadata, dataNormalizer, dataProtector, defaultMerger)
{ }
}
在配置服务中,我向工厂 function 注册了范围服务
services.AddScoped<UniqueRowKeyUserStore>(StartupService.NewUserStore);
StartupService.NewUserStore是创建 UniqueRowKeyUserStore 实例的工厂方法
public static UniqueRowKeyUserStore NewUserStore(IServiceProvider arg)
{
return new UniqueRowKeyUserStore(new DefaultMetadata(), new DefaultNormalizer(), new DefaultProtecttor(), new DefaultSplitter());
}
正如您所看到的,我使用 Factory 方法来创建实例,因此期望DI 不应该抱怨 IStoreMetadata 或构造函数中预期的其他接口。
但是我在启动过程中收到错误,它看起来确实像 asp.net 核心 3.0 中的 DI 忽略了工厂方法?
InvalidOperationException:尝试激活“UniqueRowKeyUserStore”时无法解析“IStoreMetadata”类型的服务。
我不确定我在 ASP.NET Core 3.0 中做错了什么
如果其他东西稍后注入相同的 class (例如, AddIdentity
),可能会发生这种情况。
我无法重现您描述的问题,并且在我的身份 package 中没有相同的类(我猜您使用的是扩展的?),所以我必须创建自己的:
services.AddScoped<MyUserStore>(sp => new MyUserStore(new DefaultComponent2()));
services.AddScoped<MyUserStore>(sp => new MyUserStore(new DefaultComponent()));
services.AddScoped<MyUserStore>();
如果我只有前两行,那么每当我请求MyUserStore
时,我都会得到DefaultComponent()
。 但是,如果我添加第 3 行(并且我从未注册任何IComponent
),我会收到与您描述的相同的错误消息。
.AddUserStore<UniqueRowKeyUserStore>()
是导致问题的原因。
/// <summary>
/// Adds an <see cref="IUserStore{TUser}"/> for the <see cref="UserType"/>.
/// </summary>
/// <typeparam name="TStore">The user store type.</typeparam>
/// <returns>The current <see cref="IdentityBuilder"/> instance.</returns>
public virtual IdentityBuilder AddUserStore<TStore>() where TStore : class
=> AddScoped(typeof(IUserStore<>).MakeGenericType(UserType), typeof(TStore));
注意它是如何添加为IUserStore<>
所以你是正确的,它没有调用你的实现注册。 它正在寻找抽象。
感谢@LukeVo 和@Nkosi ......评论帮助我调试了这个问题。 我不知道为什么完全相同的代码在 asp.net 核心 2.2 中工作,但 asp.net 核心 3.0 中的 DI 会抱怨重复注册服务并忽略工厂方法。
我有自定义 UserStore 和 UserRoleStore 并且我使用 Identity 注册如下...我必须删除.AddUserStore()和.AddUserRoleStore()因为我要用工厂方法注册我的客户商店,以便我可以传递其他数据(接口 IStoreMetaData、ILookupNormalizer 等...)
services.AddIdentity<UniqueRowKeyUser, UserRole>()
.AddRoles<UserRole>()
.AddUserManager<UserManager<UniqueRowKeyUser>>()
.AddRoleManager<RoleManager<UserRole>>()
.AddSignInManager<SignInManager<UniqueRowKeyUser>>()
.AddErrorDescriber<TranslatedIdentityErrorDescriptor>()
.AddDefaultTokenProviders();
现在注册 Factory 方法,下面的代码将不起作用,因为 DI 无法 map 到 AddIdentity 注册的存储类型,如上所述。
services.AddScoped<UniqueRowKeyUserStore>(StartupService.NewUserStore);
services.AddScoped<UserRoleStore>(StartupService.NewUserRoleStore);
所以我不得不更改服务注册并使用 IUserStore 和 IRoleStore与我的工厂方法,现在它的工作......
services.AddScoped<IUserStore<UniqueRowKeyUser>, UniqueRowKeyUserStore>(StartupService.NewUserStore);
services.AddScoped<IRoleStore<UserRole>, UserRoleStore>(StartupService.NewUserRoleStore);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.