AspIdentiy ApplicationUserManager是静态的,如何扩展,使它参与我的IoC框架
本文关键字:框架 IoC 我的 扩展 静态 ApplicationUserManager 何扩展 AspIdentiy | 更新日期: 2023-09-27 18:02:36
在新的asp.net MVC应用程序中,您现在可以免费获得AspIdentity的好处。
有一条无害的小字"在这里插入您的电子邮件服务"。
所以我做了:
public class EmailService : IIdentityMessageService
{
private static My.Services.IEmailService _emailservice;
public EmailService(Insolvency.Services.IEmailService emailservice)
{
_emailservice = emailservice;
}
public Task SendAsync(IdentityMessage message)
{
_emailservice.SendEmail(message);
return Task.FromResult(0);
}
}
和现在的喜悦:
public class ApplicationUserManager : UserManager<ApplicationUser>
{
private My.Services.IEmailService _emailservice;
public ApplicationUserManager(IUserStore<ApplicationUser> store, My.Services.IEmailService emailservice): base(store)
{
_emailservice = emailservice;
}
public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
{
var manager = new ApplicationUserManager(new UserStore<ApplicationUser>(context.Get<ApplicationDbContext>()), _emailservice);
...
当Owin启动时,它在Startup.Auth.cs:
中调用Create on ApplicationUserManagerpublic partial class Startup
{
public void ConfigureAuth(IAppBuilder app)
{
...
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
和我使用AutoFac作为我的IoC容器,在global.asax.cs
builder.RegisterType<My.Services.EmailService>().As<IEmailService>();
如果Create方法是静态的,那么我得到:_emailService
为null
我已经看了这里:http://forums.asp.net/post/5293670.aspx,我如何创建UserManager的实例和使用autofacc提供静态工厂导出的类型。但是运气不好。
如果我改变:
private My.Services.IEmailService _emailservice;
我觉得IoC的神在摇头,我不能构建"需要对象引用"
今天我正在为同样的问题而挣扎(因为我是Asp.Identity的新手,所以还在努力)。我是这样做的:
-
Startup.cs(使用自己的容器)
public class Startup { public void Configuration(IAppBuilder app) { var authConfigurator = new AuthConfigurator(); authConfigurator.ConfigureAuth(app); var unityContainer = UnityConfig<MvcUnityDependencyContainer>.UseContainer(); //Asp identity registration IDataProtectionProvider dataProtectionProvider = app.GetDataProtectionProvider(); unityContainer.RegisterInstance(dataProtectionProvider); unityContainer.RegisterType<DbContext, ApplicationDbContext>(new HierarchicalLifetimeManager()); unityContainer.RegisterType<UserManager<ApplicationUser, int>>(new HierarchicalLifetimeManager()); unityContainer.RegisterType IIdentityMessageService, EmailService>(); unityContainer.RegisterType<IUserStore<ApplicationUser, int>, UserStore<ApplicationUser, CustomRole, int, CustomUserLogin, CustomUserRole, CustomUserClaim>>( new InjectionConstructor(new ApplicationDbContext())); unityContainer.RegisterType<IIdentityMessageService, EmailService>(); } }
-
ApplicationUserManager(我删除了静态方法Create):
public class ApplicationUserManagerService : UserManager<ApplicationUser, int> { public ApplicationUserManagerService(IUserStore<ApplicationUser, int> store, IIdentityMessageService emailService, IDataProtectionProvider dataProtectionProvider) : base(store) { UserTokenProvider = new EmailTokenProvider<ApplicationUser, int>(); EmailService = emailService; Configure(dataProtectionProvider); } private void Configure(IDataProtectionProvider dataProtectionProvider) { // Configure validation logic for usernames UserValidator = new UserValidator<ApplicationUser, int>(this) { AllowOnlyAlphanumericUserNames = false, RequireUniqueEmail = true }; // Configure validation logic for passwords PasswordValidator = new PasswordValidator { RequiredLength = 1, RequireNonLetterOrDigit = false, RequireDigit = false, RequireLowercase = false, RequireUppercase = false, }; // 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 in here. RegisterTwoFactorProvider("PhoneCode", new PhoneNumberTokenProvider<ApplicationUser, int> { MessageFormat = "Your security code is: {0}" }); RegisterTwoFactorProvider("EmailCode", new EmailTokenProvider<ApplicationUser, int> { Subject = "Security Code", BodyFormat = "Your security code is: {0}" }); if (dataProtectionProvider != null) { UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser, int>(dataProtectionProvider.Create("ASP.NET Identity")); } } }
控制器 public class AccountController : Controller { private ApplicationUserManagerService _userManagerService; public AccountController(ApplicationUserManagerService userManagerService) { Contract.Requires(userManagerService != null); _userManagerService = userManagerService; } /*....*/ }
ApplicationUser
public class ApplicationUser : IdentityUser<int, CustomUserLogin, CustomUserRole, CustomUserClaim> { public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser, int> manager) { var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie); return userIdentity; } } public class CustomRole : IdentityRole<int, CustomUserRole> { public CustomRole() { } public CustomRole(string name) { Name = name; } } public class CustomUserClaim : IdentityUserClaim<int> { } public class CustomUserLogin : IdentityUserLogin<int> { } public class CustomUserRole : IdentityUserRole<int> { }
这对我有效,但请随时提出更好的解决方案。
今天我为此抗争了很长时间,最后,最简单的事情就是这样做。
内部public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
方法,找到这些行代码。
manager.EmailService = new EmailService(); manager.SmsService = new SmsService();
然后改成这个
manager.EmailService = new EmailService(DependencyResolver.Current.GetService<Insolvency.Services.IEmailService>());
我不喜欢服务定位器模式,但是所有的MVC模板化代码都使用它,最好不要与框架对抗。
使用Unity,我将以下内容添加到UnityConfig.cs中的RegisterTypes(IUnityContainer container)
:
container.RegisterType<ApplicationUserManager>(New InjectionFactory(x => HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>()));
这将获取已经为Startup.ConfigureAuth(IAppBuilder app)
中的OwinContext创建的ApplicationUserManager ,并使其可用于注入。您可以将其他所有内容保持默认设置,包括ApplicationUserManager的静态Create
方法。