簡體   English   中英

ASP.Net Core 3.0 依賴注入忽略工廠方法?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM