简单注射器 - 注册 ASP.NET 身份

Simple Injector - Registering ASP.NET Identity

我一直在关注这篇文章以尝试获得 ASP.NET Identity 使用 Simple Injector,但我一直 运行 遇到一些问题。 https://github.com/simpleinjector/SimpleInjector/issues/597

我将 SimpleInjectorInitializer class 设置为如下所示:

public class SimpleInjectorInitializer
{
    public static Container Initialize(IAppBuilder app)
    {
        var container = GetInitializeContainer(app);

        container.Verify();

        DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container));

        return container;
    }

    private static Container GetInitializeContainer(IAppBuilder app)
    {
        var container = new Container();

        //container.Options.DefaultScopedLifestyle = new WebRequestLifestyle();

        container.RegisterInstance(app);

        container.Register<ApplicationUserManager>();

        container.Register(() => new ApplicationDbContext("Your constring goes here"), Lifestyle.Scoped);

        container.Register<IUserStore<ApplicationUser>>(() => new UserStore<ApplicationUser>(container.GetInstance<ApplicationDbContext>()), Lifestyle.Scoped);

        container.RegisterInitializer<ApplicationUserManager>(manager => InitializeUserManager(manager, app));

        container.Register<SignInManager<ApplicationUser, string>, ApplicationSignInManager>(Lifestyle.Scoped);

        container.Register(() => container.IsVerifying ? new OwinContext(new Dictionary<string, object>()).Authentication : HttpContext.Current.GetOwinContext().Authentication, Lifestyle.Scoped);

        container.RegisterMvcControllers(Assembly.GetExecutingAssembly());

        return container;
    }

    private static void InitializeUserManager(ApplicationUserManager manager, IAppBuilder app)
    {
        manager.UserValidator = new UserValidator<ApplicationUser>(manager)
        {
            AllowOnlyAlphanumericUserNames = false,
            RequireUniqueEmail = true
        };

        //Configure validation logic for passwords
        manager.PasswordValidator = new PasswordValidator()
        {
            RequiredLength = 8,
            RequireNonLetterOrDigit = true,
            RequireDigit = true,
            RequireLowercase = true,
            RequireUppercase = true,
        };

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

        // Register two factor authentication providers. This application uses Phone and Emails as a step of receiving a code for verifying the user
        // You can write your own provider and plug it in here.
        manager.RegisterTwoFactorProvider("Phone Code", new PhoneNumberTokenProvider<ApplicationUser>
        {
            MessageFormat = "Your security code is {0}"
        });
        manager.RegisterTwoFactorProvider("Email Code", new EmailTokenProvider<ApplicationUser>
        {
            Subject = "Security Code",
            BodyFormat = "Your security code is {0}"
        });

        manager.EmailService = new EmailService();
        manager.SmsService = new SmsService();

        var dataProtectionProvider = app.GetDataProtectionProvider();
        if (dataProtectionProvider != null)
        {
            manager.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser>(dataProtectionProvider.Create("ASP.NET Identity"));
        }
    }
}

当我 运行 我的应用出现错误 To be able to use the Lifestyle.Scoped property, please ensure that the container is configured with a default scoped lifestyle by setting the Container.Options.DefaultScopedLifestyle property with the required scoped lifestyle for your type of application.

为了解决这个问题,我尝试添加 container.Options.DefaultScopedLifestyle = new WebRequestLifestyle(); 如果我有那一行,尽管我收到错误:

The configuration is invalid. The following diagnostic warnings were reported:

-[Lifestyle Mismatch] ApplicationSignInManager (Web Request) depends on ApplicationUserManager (Transient).

-[Short Circuited Dependency] AccountController might incorrectly depend on unregistered type ApplicationSignInManager (Transient) instead of SignInManager<ApplicationUser, String> (Web Request).

-[Short Circuited Dependency] ManageController might incorrectly depend on unregistered type ApplicationSignInManager (Transient) instead of SignInManager<ApplicationUser, String> (Web Request).

-[Disposable Transient Component] ApplicationUserManager is registered as transient, but implements IDisposable.

-[Disposable Transient Component] ApplicationSignInManager is registered as transient, but implements IDisposable.

-[Ambiguous Lifestyles] The registration for SignInManager<ApplicationUser, String> (Web Request) maps to the same implementation (ApplicationSignInManager) as the registration for ApplicationSignInManager (Transient) does, but the registration maps to a different lifestyle. This will cause each registration to resolve to a different instance.

-[Ambiguous Lifestyles] The registration for ApplicationSignInManager (Transient) maps to the same implementation (ApplicationSignInManager) as the registration for SignInManager<ApplicationUser, String> (Web Request) does, but the registration maps to a different lifestyle. This will cause each registration to resolve to a different instance.

我不知道下一步该怎么做,如有任何建议,我们将不胜感激。

Simple Injector 给出的错误信息量可能有点多,但您可以将这些信息提炼为两个独立的问题:

  • ApplicationUserManager 注册为 Transient
  • 类型错误地依赖于未注册的类型 ApplicationSignInManager(瞬态)而不是 SignInManager<ApplicationUser, String>(Web 请求)。

您当然应该阅读 Diagnostic Services documentation page in the Simple Injector documentation and especially read about Lifestyle Mismatches, Disposable Transient Components and Short-Circuited Dependencies 以了解 Simple Injector 警告的内容以及如何解决问题。

简而言之,修复有两个方面:

  1. ApplicationUserManager 的注册从 Transient 更改为 Scoped 以防止它的生命周期过短并确保它被处理掉。另请阅读 this part of the documentation 以从 Simple Injector 的上下文中了解 Transient 和 Scoped 之间的区别。
  2. 确保类型(即 AccountControllerManageController)不依赖于 ApplicationSignInManager(在它们的构造函数中),而是依赖于它的基类型 SignInManager<ApplicationUser, String>.