これが私の設定です:
public class ApplicationUser : IdentityUser<Guid>
{
}
public class ApplicationRole : IdentityRole<Guid>
{
}
public class ApplicationUserLogin : IdentityUserLogin<Guid>
{
}
public class ApplicationUserClaim : IdentityUserClaim<Guid>
{
}
public class ApplicationRoleClaim : IdentityRoleClaim<Guid>
{
}
これが私のUserStoreの定義です
public class ApplicationUserStore : UserStore<ApplicationUser, ApplicationRole, MyContext, Guid>
{
public ApplicationUserStore(MyContext context, IdentityErrorDescriber describer = null)
: base(context, describer)
{
}
}
これが私のUserManagerの定義です
public class ApplicationUserManager : UserManager<ApplicationUser>
{
public ApplicationUserManager(IUserStore<ApplicationUser> store, IOptions<IdentityOptions> optionsAccessor,
IPasswordHasher<ApplicationUser> passwordHasher, IEnumerable<IUserValidator<ApplicationUser>> userValidators,
IEnumerable<IPasswordValidator<ApplicationUser>> passwordValidators, ILookupNormalizer keyNormalizer,
IdentityErrorDescriber errors, IEnumerable<IUserTokenProvider<ApplicationUser>> tokenProviders,
ILoggerFactory logger, IHttpContextAccessor contextAccessor)
: base(
store, optionsAccessor, passwordHasher, userValidators, passwordValidators, keyNormalizer, errors,
tokenProviders, logger, contextAccessor)
{
}
}
これが私のDbContextの定義です:
public class MyContext : IdentityDbContext<ApplicationUser, ApplicationRole, Guid>
{
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
}
}
そして、これが私のStartup.csです
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddEntityFramework()
.AddSqlServer()
.AddDbContext<MyContext>(options => options.UseSqlServer(Configuration.Get("Data:DbConnection")));
services.AddIdentity<ApplicationUser, ApplicationRole>()
.AddEntityFrameworkStores<MyContext, Guid>()
.AddUserStore<ApplicationUserStore>()
.AddRoleStore<ApplicationRoleStore>()
.AddUserManager<ApplicationUserManager>()
.AddRoleManager<ApplicationRoleManager>()
.AddDefaultTokenProviders();
var builder = new ContainerBuilder();
builder.Populate(services);
var container = builder.Build();
return container.Resolve<IServiceProvider>();
}
このコンストラクターの依存関係は機能します。
public AccountController(UserManager<ApplicationUser> userManager, SignInManager<ApplicationUser> signInManager)
これはしません:
public AccountController(ApplicationUserManager userManager, SignInManager<ApplicationUser> signInManager)
誰かが私が間違っていることについて考えを持っていますか?
DIは一般に、インターフェース主導の開発を目的としています。 .AddUserManager<ApplicationUserManager>()
は、サービスインターフェイスではなく、実装UserManager<>
を指定します。つまり、UserManager<ApplicationUser>
を取得して、その方法でのみ使用することを期待しています。 ApplicationUserManager
が表示されます。
ApplicationUserManager
で使用したい追加のメソッドがあると想定しています。 そうでない場合依存関係コンストラクターをその動作方法で使用し、インターフェイス駆動型開発を楽しんでください。そうであれば、次のようになります。 3つのオプション:
継承ではなく構成を介して拡張を使用します。UserManager<>
から継承するのではなく、ApplicationUserManager
をラッパークラスとして記述します。コンストラクタに含めることができます。これにより、ApplicationUserManager
内で必要なすべての機能が提供されます。
DIフレームワークにそのまま追加します。UserManager<>
には実際の状態がないため、これは思ったほど難しくありません。
services.AddScoped<ApplicationUserManager>();
ここでの欠点は、ユーザーのスコープに実際に2つのUserManager<>
オブジェクトがあることです。その結果、いくつかの非効率性が生じる可能性があります。現在のコードの状態からすると、そうではないと思います。
拡張メソッドとして記述します。UserManager<>
の基本機能だけでなく、多数の依存関係がある場合、これは非常に複雑になる可能性があります。
現在ASP.NET Core 1.1を使用しており、この動作は修正されています。
自分のUserManagerとUserStoreを簡単に実装でき、bootstrapアプリは次のようになります:
// identity models
services
.AddIdentity<ApplicationUser, ApplicationRole>()
.AddEntityFrameworkStores<ApplicationDbContext, Guid>()
.AddUserManager<ApplicationUserManager>()
.AddUserStore<ApplicationUserStore>()
.AddDefaultTokenProviders();
userManagerとUserStoreの両方を問題なくコントローラーに挿入します。
public AccountController(
IIdentityServerInteractionService interaction,
IClientStore clientStore,
IHttpContextAccessor httpContextAccessor,
ApplicationUserManager userManager,
SignInManager<ApplicationUser> signInManager,
IEmailSender emailSender,
ISmsSender smsSender,
ILoggerFactory loggerFactory)
{
_interaction = interaction;
_userManager = userManager;
_signInManager = signInManager;
_emailSender = emailSender;
_smsSender = smsSender;
_logger = loggerFactory.CreateLogger<AccountController>();
_account = new AccountService(_interaction, httpContextAccessor, clientStore);
}
私はこれを思いついた:
// Extract IApplicationUserManager interface with all methods you are using
public class ApplicationUserManager : UserManager<ApplicationUser>, IApplicationUserManager
// Register your custom user manager
services.AddIdentity<ApplicationUser, ApplicationRole>()
.AddUserManager<ApplicationUserManager>();
// Return same scoped instance whenever you injecting your custom user manager into any constructor
services.AddScoped<IApplicationUserManager>(s => s.GetService<ApplicationUserManager>());