c# - 依赖注入(inject)循环依赖.NET Core 2.0

标签 c# asp.net-core dependency-injection circular-dependency asp.net-2.0

我希望我的 ApplicationContext 构造函数将 UserManager 作为参数,但我在依赖注入(inject)方面遇到了问题。

代码:

public class ApplicationContext : IdentityDbContext<ApplicationUser>
{
    private IHttpContextAccessor _contextAccessor { get; set; }
    public ApplicationUser ApplicationUser { get; set; }
    private UserManager<ApplicationUser> _userManager;

    public ApplicationContext(DbContextOptions<ApplicationContext> options, IHttpContextAccessor contextAccessor, UserManager<ApplicationUser> userManager)
        : base(options)
    {
        _contextAccessor = contextAccessor;
        var user = _contextAccessor.HttpContext.User;
        _userManager = userManager;
        ApplicationUser = _userManager.Users.FirstOrDefault(u => u.Id == _userManager.GetUserId(user));
    }
}

startup.cs 中:

public void ConfigureServices(IServiceCollection services)
{
    // Add framework services.
    services.AddDbContext<ApplicationContext>(options =>
        options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"), b => b.MigrationsAssembly("RCI.App")));

    services.AddIdentity<ApplicationUser, IdentityRole>()
        .AddEntityFrameworkStores<ApplicationContext>()
        .AddDefaultTokenProviders();

    services.AddAuthentication();

    services.AddMvc();

    // Add application services.
    services.AddTransient<IEmailSender, AuthMessageSender>();
    services.AddTransient<ISmsSender, AuthMessageSender>();
    services.AddTransient<IHttpContextAccessor, HttpContextAccessor>();

    services.AddOptions();

}

错误信息:

A circular dependency was detected for the service of type 'Microsoft.AspNetCore.Identity.UserManager`1[RCI.App.Models.ApplicationUser]'.

谁能指出我做错了什么?

最佳答案

如果您实际上不需要 UserManager在构造函数中,您可以存储对 IServiceProvider 的引用相反:

private IHttpContextAccessor _contextAccessor { get; set; }
public ApplicationUser ApplicationUser { get; set; }
private IServiceProvider _services;

public ApplicationContext(DbContextOptions<ApplicationContext> options,
    IHttpContextAccessor contextAccessor, IServiceProvider services)
    : base(options)
{
    _contextAccessor = contextAccessor;
    var user = _contextAccessor.HttpContext.User;
    _services = services;
}

然后,当您真正需要 ApplicationUser 时,例如打电话GetRequiredService<ApplicationUser>() (在 Microsoft.Extensions.DependencyInjection 中定义):

var manager = _services.GetRequiredService<UserManager<ApplicationUser>>();
var user = manager.Users.FirstOrDefault(u => u.Id == _userManager.GetUserId(user));

当然,你可以使用Lazy<T>第一次延迟加载管理器或用户,然后存储对它的引用。

一般来说,@poke 关于重新架构以避免此类循环依赖的说法是正确的,但将此答案留在此处以防其他人遇到类似问题并且重构不是一种选择。

关于c# - 依赖注入(inject)循环依赖.NET Core 2.0,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46354041/

相关文章:

c# - Specflow:步骤的基类

amazon-web-services - .NET Core API Gateway (AWS) 如何设置依赖注入(inject) (DI) 以使用 MemCached .NET Core 包、基于 DI 的记录器等

.net - DI Control-Freak 反模式 : Having trouble understanding

c# - UserStore 每个 HttpRequest 的 Unity IoC 生命周期

c# - 如何将 WCF 服务的引用添加到 .Net CF 2.0 应用程序?

c# - 在 C++ 中使用 Mono 获取程序集类

c# 强制数字 updown 只接受带有 try-parse 的正整数

c# - 数据是通过 AJAX 传递给操作的对象数组

c# - ASP.NET Core 后台任务中的用户 session

asp.net-core - 如何使用 ASP.NET CORE 在 View 中获取编译时错误