如何统一注入ApplicationUserManager

How to inject ApplicationUserManager with unity

ApplicationUserManager 定义如下:

public class ApplicationUserManager : UserManager<ApplicationUser, int>
    { 
        public ApplicationUserManager(IUserStore<ApplicationUser, int> store)
        : base(store)
        {
        }

       public override Task<IdentityResult> CreateAsync(ApplicationUser user, string password)
        {
            var result = base.CreateAsync(user, password);
            //... 
            Repository.DoSomething(...); //Repository is null here
            //..
        }          

       [Dependency]
       public IRepository Repository { get; set; }
    }

出于某种原因,我的存储库没有被注入。 Repository 总是 null

我的统一配置中也有这一行

.RegisterType<ApplicationUserManager>(new HierarchicalLifetimeManager())

如何注入?

更新 N:

这是来自我的控制器的代码;我如何获得 UserManager:

public ApplicationUserManager UserManager
{
    get
    {
        return _userManager ?? Request.GetOwinContext().GetUserManager<ApplicationUserManager>();
    }
    private set
    {
        _userManager = value;
    }
}

public async Task<IHttpActionResult> Register(RegisterBindingModel model)
    {
        var user = new ApplicationUser() { UserName = model.Email, Email = model.Email };
         //calling my implemintation
         IdentityResult result = await UserManager.CreateAsync(...);
    }

我当前的统一配置

.RegisterType<IUserStore<ApplicationUser, int>, CustomUserStore>(new HierarchicalLifetimeManager())
.RegisterType<IAuthenticationManager>(new InjectionFactory(o => HttpContext.Current.GetOwinContext().Authentication))
.RegisterType<UserManager<ApplicationUser, int>, ApplicationUserManager>()
.RegisterType<DbContext, ApplicationDbContext>(new HierarchicalLifetimeManager())
.RegisterType<AccountController>(new InjectionConstructor())
.RegisterType<ApplicationDbContext>(new HierarchicalLifetimeManager())
.RegisterType<ApplicationUserManager>()

更新 N+1:

我发现 Unity.Mvc 包没有注入 WebApi 控制器。我使用这个 method 来注入 WebApi 控制器。我试图删除 Unity.Mvc 包但得到 Identity 抛出错误。根据我的理解,因为 Unity 无法实例化一些 Identity types 但是它们在设置 Mvc 容器的情况下被配置和工作。 所以我带回 Unity.Mvc 包来注入我的 Identity types。否则,正如我上面所解释的,当 Unity 解析 Identity types.

时,它会在空引用上抛出不同的类型

所以我的项目中现在有两个容器 Unity.Mvc 注入 DependencyResolver.SetResolver(new UnityDependencyResolver(container)); 需要解析 Identity types 和自定义 WebApi 注入 config.DependencyResolver = new UnityResolver(container); 需要的容器使用相同的 UnityConfig 注入 WebApi contorllers。

更新 3:

我变了 这个:

app.CreatePerOwinContext(() => DependencyResolver.Current.GetService<ApplicationUserManager>());

至此

app.CreatePerOwinContext(() => UnityConfig.GetConfiguredContainer().Resolve<ApplicationUserManager>());

Startup.ConfigureAuth() 中,现在我的 WebApi 容器完全正常工作并构建了所有必需的 Identity types 所以我可以禁用 Mvc 容器,甚至可以完全删除 Unity.Mvc 包。

感谢@Sam Farajpour Ghamari 澄清了很多事情。

因为您将 UserManager 与 OWIN 一起使用。您需要将 OWIN 容器与 unity 集成。因为我没有看到你的代码的其他部分,特别是 OWIN 启动方法。我展示了一个简单的示例来演示如何自己执行此操作。

首先,如果您使用 Entity Framework,您必须将您的上下文注册到 unity。第二个注册身份需要它们的其他类型是这样的:

container.RegisterType<DbContext, MyDbContext>(new PerRequestLifetimeManager());
container.RegisterType<IUserStore<ApplicationUser>,
    UserStore<ApplicationUser>>(new PerRequestLifetimeManager());
container.RegisterType<ApplicationUserManager>(new PerRequestLifetimeManager());
container.RegisterType<IAuthenticationManager>(
    new InjectionFactory(c => HttpContext.Current.GetOwinContext().Authentication))
container.RegisterType<ApplicationSignInManager>(new PerRequestLifetimeManager());

然后像这样更改 ApplicationUserManager 的构造函数:

public ApplicationUserManager(IUserStore<ApplicationUser> store,
    IRepository repo)
        : base(store)
{
    this.Repository=repo;
    // put your other configuration here instead of putting in 
    // static ApplicationUserManagerCreate() method.
    this.UserValidator = new UserValidator<ApplicationUser>(this)
    {
        AllowOnlyAlphanumericUserNames = false,
        RequireUniqueEmail = true
    };
        // Configure validation logic for passwords
    this.PasswordValidator = new PasswordValidator
    {
        RequiredLength = 6,
        RequireNonLetterOrDigit = true,
        RequireDigit = true,
        RequireLowercase = true,
        RequireUppercase = true,
    };

        // Configure user lockout defaults
    this.UserLockoutEnabledByDefault = true;
    this.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(5);
    this.MaxFailedAccessAttemptsBeforeLockout = 5;

    // and your other configurations
}

现在在您的 Startup.ConfigureAuth() 方法中更改以下行:

public void ConfigureAuth(IAppBuilder app)
{
    app.CreatePerOwinContext(EFDbContext.Create);
    app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
    app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);
    // others
}

至:

public void ConfigureAuth(IAppBuilder app)
{
    app.CreatePerOwinContext(()=> DependencyResolver.Current.GetService<ApplicationUserManager>());
    app.CreatePerOwinContext(()=> DependencyResolver.Current.GetService<ApplicationSignInManager>());
    // other configs
}

此外,我们不再需要 ApplicationUserManager Create()ApplicationSignInManager.Create() 方法,我们可以轻松删除它们,因为 Unity 现在负责创建我们的 类。

现在我们将 Identity 与 unity 完全结合起来。对于更多和复杂的信息,我强烈建议您阅读 this awesome blog post