1

私はASP.NET Core MVCには比較的新しいので、依存性注入に関する問題にぶち間かかっています。ASP.NET Core MVC Dependency Injection issue

私は、EFデータベースコンテキストクラスを共有したい複数のプロジェクトを持つソリューションを用意しています。私は構成マネージャのためのインターフェイスを定義したので、プロジェクト間で共通の設定を共有できますが、プロジェクト固有の設定もあります。

様々なAPIの依存性注入を実行している

"System.InvalidOperationException: Unable to resolve service for type IConfigManager"

エラーで失敗します。

Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddl‌​eware[0] An unhandled exception has occurred while executing the request System.InvalidOperationException: Unable to resolve service for type 'NovaSec.Core.IConfigManager' while attempting to activate 'NovaSec.Core.Contexts.CustomDbContext'. at Microsoft.Extensions.DependencyInjection.ServiceLookup.Servi‌​ce.PopulateCallSites‌​(ServiceProvider provider, ISet`1 callSiteChain, ParameterInfo[] parameters, Boolean throwIfCallSiteNotFound)

DBContextClassは、他のプロジェクトで参照しているクラスライブラリプロジェクトの一部です。

なぜ動作しないのかわかりません。誰かが助けてくれてこれを私に説明できますか?

DBContextクラス

public class CustomDbContext : IdentityDbContext<CustomIdentity, CustomRole, string> 
    { 
     public CustomDbContext(DbContextOptions<CustomDbContext> options, IConfigManager configManager) : base(options) 
     { 
      var optionsBuilder = new DbContextOptionsBuilder<CustomDbContext>(); 
      optionsBuilder.UseSqlite(configManager._config.ConnectionStrings.FirstOrDefault(c => c.id == "IdentityDatabase").connectionString); 
     } 
    } 

コンフィグマネージャのインターフェースと実装クラス

public interface IConfigManager 
{ 
    IAppConfig _config { get; set; } 
} 

public class ConfigManager : IConfigManager 
{ 
    public IAppConfig _config { get; set; } 
    public ConfigManager(IAppConfig config) 
    { 

    } 
} 

起動方法

public void ConfigureServices(IServiceCollection services) 
{ 
    services.AddSingleton<IConfigManager, ConfigManager>(config => 
    { 
     return new ConfigManager(_config); 
    }); 
    IServiceProvider serviceProvider = services.BuildServiceProvider(); 
    _configManager = (ConfigManager)serviceProvider.GetService<IConfigManager>(); 
    services.AddDbContext<CustomDbContext>(); 
    services.AddIdentity<CustomIdentity, CustomRole>(config => { 
     config.SignIn.RequireConfirmedEmail = true; 
    }) 
     .AddEntityFrameworkStores<CustomDbContext>() 
     .AddDefaultTokenProviders(); 
    services.AddIdentityServer() 
    .AddInMemoryClients(_configManager.GetClients()) 
    .AddInMemoryIdentityResources(_configManager.GetIdentityResources()) 
    .AddInMemoryApiResources(_configManager.GetApiResources()) 
    .AddTemporarySigningCredential() 
    .AddAspNetIdentity<CustomIdentity>(); 

} 
+0

も協力することをい元気?問題を再現するために使用できる[mcve]を提供してください。 – Nkosi

+0

configメソッド内にサービスプロバイダを作成せず、プロバイダを作成した後にサービスを追加しないでください。 –

答えて

0

私はついにそれを得ました。最終的な結果は次のとおりです。

DbContextクラス

public class CustomDbContext : IdentityDbContext<CustomIdentity, CustomRole, string> 
{ 
    private readonly IConfigManager _configManager; 
    public CustomDbContext(DbContextOptions<CustomDbContext> options, IConfigManager configManager) : base(options) 
    { 
     this._configManager = configManager; 
    } 

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) 
    { 
     optionsBuilder.UseSqlite(_configManager._config.ConnectionStrings.FirstOrDefault(c => c.id == "IdentityDatabase").connectionString); 
    } 
} 

スタートアップ

public IConfigurationRoot Configuration { get; set; } 
public ConfigManager ConfigManager { get; set; } 
public AppConfig Config { get; set; } 
// This method gets called by the runtime. Use this method to add services to the container. 
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 
public Startup(IHostingEnvironment env) 
{ 
    var builder = new ConfigurationBuilder() 
    .SetBasePath(Directory.GetCurrentDirectory()) 
    .AddJsonFile("appsettings.json") 
    .AddEnvironmentVariables(); 

    this.Configuration = builder.Build(); 
    this.Config = new AppConfig(); 
    this.Configuration.Bind(this.Config); 
    this.ConfigManager = new ConfigManager(this.Config); 
} 

public void ConfigureServices(IServiceCollection services) 
{ 
    services.AddSingleton<IConfigManager, ConfigManager>(provider => this.ConfigManager); 
    services.AddDbContext<CustomDbContext>(); 
    services.AddIdentity<CustomIdentity, CustomRole>(config => { 
     config.SignIn.RequireConfirmedEmail = true; 
    }) 
     .AddEntityFrameworkStores<CustomDbContext>() 
     .AddDefaultTokenProviders(); 
    services.AddIdentityServer() 
    .AddInMemoryClients(this.ConfigManager.GetClients()) 
    .AddInMemoryIdentityResources(this.ConfigManager.GetIdentityResources()) 
    .AddInMemoryApiResources(this.ConfigManager.GetApiResources()) 
    .AddTemporarySigningCredential() 
    .AddAspNetIdentity<CustomIdentity>(); 
} 

CONFIGMANAGER

public interface IConfigManager 
{ 
    IAppConfig _config { get; set; } 
} 

public class ConfigManager : IConfigManager 
    { 
     public IAppConfig _config { get; set; } 
     public ConfigManager(IAppConfig config) 
     { 
      this._config = config; 
     } 

    } 
} 
2

この段階では、手動でマネージャを作成し、設定に使用してからサービスコレクションに登録する方がよいでしょう。あなたはまた、起動時にコンテキストを設定する必要があります

更新コンテキスト

public class CustomDbContext : IdentityDbContext<CustomIdentity, CustomRole, string> { 
    public CustomDbContext(DbContextOptions<CustomDbContext> options) : base(options) { } 
} 

public void ConfigureServices(IServiceCollection services) { 
    var _configManager = new ConfigManager(_config); //Create new instance 
    services.AddSingleton<IConfigManager>(provider => _configManager); // add as singleton 

    services.AddDbContext<CustomDbContext>(options => 
     options.UseSqlite(_configManager._config.ConnectionStrings.FirstOrDefault(c => c.id == "IdentityDatabase").connectionString) 
    ); 

    services.AddIdentity<CustomIdentity, CustomRole>(config => { 
     config.SignIn.RequireConfirmedEmail = true; 
    }) 
     .AddEntityFrameworkStores<CustomDbContext>() 
     .AddDefaultTokenProviders(); 

    services.AddIdentityServer() 
     .AddInMemoryClients(_configManager.GetClients()) 
     .AddInMemoryIdentityResources(_configManager.GetIdentityResources()) 
     .AddInMemoryApiResources(_configManager.GetApiResources()) 
     .AddTemporarySigningCredential() 
     .AddAspNetIdentity<CustomIdentity>(); 

} 
+0

ありがとう!私もそれを試みた。失敗:Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware [0] 要求の実行中に未処理の例外が発生しました System.InvalidOperationException:アクティブ化しようとしているときに 'NovaSec.Core.IConfigManager'タイプのサービスを解決できません'NovaSec.Core.Contexts.CustomDbContext'。 (Microsoft.Extensions.DependencyInjection.ServiceLookup.Service.PopulateCallSites(ServiceProviderプロバイダー、ISet'1 callSiteChain、ParameterInfo []パラメーター、Boolean throwIfCallSiteNotFound) –

+0

このエラーはどこにスローされますか。 – Nkosi

+0

アプリケーションで任意のコントローラーを呼び出すと、私が単純にDBContextClassを services.AddDbContext (options => options.UseSqlite( "Data Source = idenitysource.db"))のように直接設定すると、 すべて正常に動作します。これは、configManagerオブジェクトを受け取らないCustomDbContextクラスのコンストラクタに関連しているようです。 –

関連する問題