簡體   English   中英

ASP.NET Core-依賴注入-IdentityServer4 DbContext

[英]ASP.NET Core - Dependency Injection - IdentityServer4 DbContext

我一直在嘗試尋找最好/首選的方法是讓我的RoleService獲得ConfigurationDbContext (IdentityServer4)。

我真的很想解耦,以便我的RoleService可以測試。

我找到訪問ConfigurationDbContext的唯一方法是通過在Startup.cs創建public static IServiceProvider

public class Startup
{
    private readonly IHostingEnvironment _environment;

    // THIS IS THE PROPERTY I USED
    public static IServiceProvider ServiceProvider { get; private set; }

    public ConfigurationDbContext GetConfigurationDbContext()
    {
        return null;
    }

    public Startup(ILoggerFactory loggerFactory, IHostingEnvironment environment)
    {
        loggerFactory.AddConsole(LogLevel.Debug);
        _environment = environment;
    }

    public void ConfigureServices(IServiceCollection services)
    {
        var connectionString = DbSettings.IdentityServerConnectionString;
        var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name;

        // configure identity server with in-memory stores, keys, clients and scopes
        var identityServerConfig = services.AddIdentityServer()
            .AddConfigurationStore(builder =>
                builder.UseSqlServer(connectionString, options =>
                    options.MigrationsAssembly(migrationsAssembly)))
            .AddOperationalStore(builder =>
                builder.UseSqlServer(connectionString, options =>
                    options.MigrationsAssembly(migrationsAssembly)))
            .AddSigningCredential(new X509Certificate2(Path.Combine(_environment.ContentRootPath, "certs", "IdentityServer4Auth.pfx"), "test"));

        identityServerConfig.Services.AddTransient<IResourceOwnerPasswordValidator, ActiveDirectoryPasswordValidator>();
        identityServerConfig.Services.AddTransient<IProfileService, CustomProfileService>();
        services.AddDbContext<ConfigurationDbContext>(options => options.UseSqlServer(connectionString));
        services.AddMvc();
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        ServiceProvider = app.ApplicationServices;
        // other code emitted
    }
}

然后在 RoleService.cs 使用此代碼

public class RoleService : IRoleService
{
    public async Task<ApiResource[]> GetApiResourcesByIds(int[] ids)
    {
        ApiResource[] result;

        using (var serviceScope = Startup.ServiceProvider.GetService<IServiceScopeFactory>().CreateScope())
        {
            var context = serviceScope.ServiceProvider.GetRequiredService<ConfigurationDbContext>();
            result =
                context.ApiResources.Where(x => ids.Contains(x.Id))
                .Include(x => x.Scopes)
                .Include(x => x.UserClaims)
                .ToArray();

            return result;
        }
    }
}

這是在RoleService.cs獲得依賴項的最佳方法嗎?

有沒有一種抽象serviceScope (因為它在using語句中,並且可能是IDisposable,所以我真的不知道是否有一種抽象獲取context

還有其他建議或最佳做法嗎?

您可以通過使用所需的依賴項作為構造函數參數創建一個構造函數來將依賴項傳遞給RoleService

根據您的壽命RoleService (不能告訴根據所提供的代碼),你會通過其中的ConfigurationDbContext直接向RoleService如果該服務已Scoped 或者,您可以傳遞IServiceScopeFactory來在服務中手動創建范圍。

就像是:

private readonly IServiceScopeFactory _scopeFactory;

public RoleService(IServiceScopeFactory scopeFactory)
{
    _scopeFactory = scopeFactory;
}

public async Task<ApiResource[]> GetApiResourcesByIds(int[] ids)
{
    using (var scope = _scopeFactory.CreateScope())
    {
        var context = scope.ServiceProvider.GetRequiredService<ConfigurationDbContext>();
    }
}

由於您的方法已與DbContext耦合(這並不是一件壞事),您可能最終會創建一個內存中ConfigurationDbContext 您使用的IdentityServer4.EntityFramework存儲庫在此處提供了一些示例進行測試。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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