diff --git a/src/Microsoft.AspNet.Identity/IdentityBuilder.cs b/src/Microsoft.AspNet.Identity/IdentityBuilder.cs index bfbbbcb78d..09d6d2b81b 100644 --- a/src/Microsoft.AspNet.Identity/IdentityBuilder.cs +++ b/src/Microsoft.AspNet.Identity/IdentityBuilder.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Reflection; using Microsoft.Framework.DependencyInjection; namespace Microsoft.AspNet.Identity @@ -159,7 +160,15 @@ namespace Microsoft.AspNet.Identity /// The . public virtual IdentityBuilder AddUserManager() where TUserManager : class { - return AddScoped(typeof(UserManager<>).MakeGenericType(UserType), typeof(TUserManager)); + var userManagerType = typeof(UserManager<>).MakeGenericType(UserType); + var customType = typeof(TUserManager); + if (userManagerType == customType || + !userManagerType.GetTypeInfo().IsAssignableFrom(customType.GetTypeInfo())) + { + throw new InvalidOperationException(Resources.FormatInvalidManagerType(customType.Name, "UserManager", UserType.Name)); + } + Services.AddScoped(customType, services => services.GetRequiredService(userManagerType)); + return AddScoped(userManagerType, customType); } /// @@ -169,7 +178,15 @@ namespace Microsoft.AspNet.Identity /// The . public virtual IdentityBuilder AddRoleManager() where TRoleManager : class { - return AddScoped(typeof(RoleManager<>).MakeGenericType(RoleType), typeof(TRoleManager)); + var managerType = typeof(RoleManager<>).MakeGenericType(RoleType); + var customType = typeof(TRoleManager); + if (managerType == customType || + !managerType.GetTypeInfo().IsAssignableFrom(customType.GetTypeInfo())) + { + throw new InvalidOperationException(Resources.FormatInvalidManagerType(customType.Name, "RoleManager", RoleType.Name)); + } + Services.AddScoped(typeof(TRoleManager), services => services.GetRequiredService(managerType)); + return AddScoped(managerType, typeof(TRoleManager)); } } } \ No newline at end of file diff --git a/src/Microsoft.AspNet.Identity/Properties/Resources.Designer.cs b/src/Microsoft.AspNet.Identity/Properties/Resources.Designer.cs index 5319301867..55c081d61c 100644 --- a/src/Microsoft.AspNet.Identity/Properties/Resources.Designer.cs +++ b/src/Microsoft.AspNet.Identity/Properties/Resources.Designer.cs @@ -122,6 +122,22 @@ namespace Microsoft.AspNet.Identity return string.Format(CultureInfo.CurrentCulture, GetString("InvalidEmail"), p0); } + /// + /// Type {0} must be derived from {1}<{2}>. + /// + internal static string InvalidManagerType + { + get { return GetString("InvalidManagerType"); } + } + + /// + /// Type {0} must be derived from {1}<{2}>. + /// + internal static string FormatInvalidManagerType(object p0, object p1, object p2) + { + return string.Format(CultureInfo.CurrentCulture, GetString("InvalidManagerType"), p0, p1, p2); + } + /// /// The provided PasswordHasherCompatibilityMode is invalid. /// diff --git a/src/Microsoft.AspNet.Identity/Resources.resx b/src/Microsoft.AspNet.Identity/Resources.resx index a630c32faa..858e22d548 100644 --- a/src/Microsoft.AspNet.Identity/Resources.resx +++ b/src/Microsoft.AspNet.Identity/Resources.resx @@ -145,6 +145,10 @@ Email '{0}' is invalid. Invalid email + + Type {0} must be derived from {1}<{2}>. + Error when the manager type is not derived correctly + The provided PasswordHasherCompatibilityMode is invalid. Error when the password hasher doesn't understand the format it's being asked to produce. diff --git a/test/Microsoft.AspNet.Identity.Test/UserManagerTest.cs b/test/Microsoft.AspNet.Identity.Test/UserManagerTest.cs index f156d5a7a7..977c39664f 100644 --- a/test/Microsoft.AspNet.Identity.Test/UserManagerTest.cs +++ b/test/Microsoft.AspNet.Identity.Test/UserManagerTest.cs @@ -31,6 +31,46 @@ namespace Microsoft.AspNet.Identity.Test Assert.NotNull(manager.Options); } + [Fact] + public void AddUserManagerWithCustomManagerReturnsSameInstance() + { + var services = new ServiceCollection() + .AddTransient, NoopUserStore>() + .AddSingleton() + .AddLogging(); + services.AddIdentity() + .AddUserManager() + .AddRoleManager(); + var provider = services.BuildServiceProvider(); + Assert.Same(provider.GetRequiredService>(), + provider.GetRequiredService()); + Assert.Same(provider.GetRequiredService>(), + provider.GetRequiredService()); + } + + [Fact] + public void AddManagerWithWrongTypesThrows() + { + var services = new ServiceCollection(); + var builder = services.AddIdentity(); + Assert.Throws(() => builder.AddUserManager>()); + Assert.Throws(() => builder.AddRoleManager>()); + Assert.Throws(() => builder.AddUserManager()); + Assert.Throws(() => builder.AddRoleManager()); + } + + public class CustomUserManager : UserManager + { + public CustomUserManager() : base(new Mock>().Object, null, null, null, null, null, null, null, null, null) + { } + } + + public class CustomRoleManager : RoleManager + { + public CustomRoleManager() : base(new Mock>().Object, null, null, null, null, null) + { } + } + [Fact] public async Task CreateCallsStore() {