Я создаю API, используя Owin, Web API, Entity Framework, ASP.NET Identity. Я использую Simple Injector в качестве моей выборки DI.
Во время процесса запуска Owin я хочу, чтобы семена базы данных с некоторыми образцами данных. Это обрабатывается классом, реализующим IDatabaseInitializer
, который выглядит примерно так:
public class MyDbInitializer : DropCreateDatabaseAlways<MyDataContext>
{
private readonly IUserManager _userManager;
public MyDbInitializer(IUserManager userManager)
{
_userManager = userManager;
}
protected override void Seed(MyDataContext context)
{
SeedIdentities();
}
private void SeedIdentities()
{
var user = new User
{
UserName = "someUsername",
Email = "[email protected]"
};
_userManager.CreateAsync(user, "Password");
}
IUserManager
является прокси для класса ASP.NET Identiy UserManager
, который косвенно зависит от IUnitOfWork
. Если вам интересно, IUserManager
регистрируется следующим образом:
container.Register(typeof(IUserManager),
() => container.GetInstance<IUserManagerFactory>().Create());
Поскольку я хочу использовать единую рабочую единицу для каждого запроса веб-API, я зарегистрировал свой IUnitOfWork
следующим образом:
container.RegisterWebApiRequest<IUnitOfWork, MyUnitOfWork>();
Это работает отлично и денди для всего, кроме как при разрешении зависимости IUserManager
в классе MyDbInitializer
. Во время запуска приложения SimpleInjector выходит из строя со следующим исключением ActivationException:
SimpleInjector.ActivationException was unhandled by user code
HResult=-2146233088
Message=The registered delegate for type IUserManagerFactory threw an exception. The IUnitOfWork is registered as 'Web API Request' lifestyle, but the instance is requested outside the context of a Web API Request.
Source=SimpleInjector
StackTrace:
at SimpleInjector.InstanceProducer.GetInstance()
at SimpleInjector.Container.GetInstance[TService]()
at Project.WebApi.CompositionRoot.SimpleInjectorCompositionRoot.<RegisterSecurityDependencies>b__c() in c:\code\Project\Project.WebApi\CompositionRoot\SimpleInjectorCompositionRoot.cs:line 130
at lambda_method(Closure )
at lambda_method(Closure )
at SimpleInjector.InstanceProducer.GetInstance()
InnerException: SimpleInjector.ActivationException
HResult=-2146233088
Message=The IUnitOfWork is registered as 'Web API Request' lifestyle, but the instance is requested outside the context of a Web API Request.
Source=SimpleInjector
StackTrace:
at SimpleInjector.Scope.GetScopelessInstance[TService,TImplementation](ScopedRegistration`2 registration)
at SimpleInjector.Scope.GetInstance[TService,TImplementation](ScopedRegistration`2 registration, Scope scope)
at SimpleInjector.Advanced.Internal.LazyScopedRegistration`2.GetInstance(Scope scope)
at lambda_method(Closure )
at SimpleInjector.InstanceProducer.GetInstance()
InnerException:
Я предполагаю, что класс Owin Startup.cs
считается вне жизненного цикла запроса веб-API, и эта инсталляция конструктора в инициализаторе базы данных терпит неудачу, потому что она вызывается классом Startup.cs
.
Я не уверен, как решить эту проблему. Должен ли я использовать гибридный образ жизни для регистрации IUnitOfWork
, или есть ли лучшее решение?