在Owin启动期间,Simple Injector无法为每个Web API请求注册类注入

Lar*_*fax 13 c# dependency-injection simple-injector asp.net-web-api owin

我正在使用Owin,Web API,实体框架,ASP.NET身份创建API.我使用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 = "some@email.com"
        };

        _userManager.CreateAsync(user, "Password");
    }
Run Code Online (Sandbox Code Playgroud)

IUserManager是ASP.NET Identiy UserManager类的代理,它间接依赖于IUnitOfWork.如果你想知道,IUserManager注册如下:

container.Register(typeof(IUserManager), 
    () => container.GetInstance<IUserManagerFactory>().Create());
Run Code Online (Sandbox Code Playgroud)

因为我想根据Web API请求使用单个工作单元,所以我已经注册了IUnitOfWork以下内容:

container.RegisterWebApiRequest<IUnitOfWork, MyUnitOfWork>();
Run Code Online (Sandbox Code Playgroud)

除了解析类中的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:
Run Code Online (Sandbox Code Playgroud)

我猜Owin Startup.cs类被认为是在Web API请求生命周期之外,并且数据库初始化程序中的构造函数注入失败,因为它是由Startup.cs类调用的.

我不确定如何解决这个问题.我应该使用混合生活方式进行注册IUnitOfWork,还是有更好的解决方案?

Ste*_*ven 26

你是对的.在启动期间,没有Web API请求.幸运的是,WebApiRequestLifestyle(所使用的RegisterWebApiRequest扩展方法)使用ExecutionContextLifestyle下盖,所以它是非常简单的"模拟" web请求如下:

// using SimpleInjector.Extensions.ExecutionContextScoping;

using (container.BeginExecutionContextScope())
{
    var initializer = container.GetInstance<MyDbInitializer>();
    intializer.InitializeDatabase();
}
Run Code Online (Sandbox Code Playgroud)