使用Owin和Simple Injector的UserManager依赖项注入



在将Simple Injector添加到我的项目中以创建将在会话的整个生命周期中存在的UserAppManager实例后,我开始收到错误:

没有无参数构造函数时出错:

尝试创建"AuthController"类型的控制器时出错。请确保控制器具有无参数的公共构造函数。

无参数构造函数错误:

为了使容器能够创建AuthController,它应该只有一个公共构造函数:它有2个。

我跟着导游(https://simpleinjector.codeplex.com/discussions/564822)以避免从Request.GetOwinContext()中获取UserManager,并使用构造函数进行操作,但运气不佳。我做错了什么?

启动:

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        ...
        app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
        app.UseWebApi(httpConfig);
        DependencyConfig.InjectDependencies(app);
    }
 }

AuthController:

[RoutePrefix("api/auth")]
public class AuthController : ApiController
{
    readonly private AppUserManager _appUserManager;
    public AuthController(AppUserManager appUserManager)
    {
        _appUserManager = appUserManager;
    }
}

DependencyConfig:

public class DependencyConfig
{
    public static void InjectDependencies(IAppBuilder app)
    {
        var container = new Container();
        container.Options.DefaultScopedLifestyle = new WebApiRequestLifestyle();
        container.Register<AppDbContext>(Lifestyle.Scoped);
        container.Register<IUserStore<AppUser>>(() => new UserStore<AppUser>(container.GetInstance<AppDbContext>()), Lifestyle.Scoped);
        container.Register<AppUserManager>(Lifestyle.Scoped);
        // other service injections
        container.RegisterWebApiControllers(GlobalConfiguration.Configuration);
        container.Verify();
        GlobalConfiguration.Configuration.DependencyResolver = new SimpleInjectorWebApiDependencyResolver(container);
        app.CreatePerOwinContext(() => container.GetInstance<AppUserManager>());
    }
}

查看您的代码:

启动.cs

app.UseWebApi(httpConfig);

依赖配置

container.RegisterWebApiControllers(GlobalConfiguration.Configuration);
container.Verify();
GlobalConfiguration.Configuration.DependencyResolver = new SimpleInjectorWebApiDependencyResolver(container);

我很清楚,您并没有将相同的HttpConfiguration实例用于WebApi配置和SimpleInjector注册。

请注意,GlobalConfiguration.Configuration!=httpConfig(手动分配var httpConfig = GlobalConfiguration.Configuration的情况除外)。

通过这种方式,您的Web API中间件不了解SimpleInjector,将使用其默认实现。因此,控制器的创建将失败。

请对Web Api和SimpleInjector注册使用相同的HttpConfiguration

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        //...
        app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
        app.UseWebApi(httpConfig);
        DependencyConfig.InjectDependencies(app, httpConfig);
    }
 }
public class DependencyConfig
{
    public static void InjectDependencies(IAppBuilder app, HttpConfiguration config)
    {
        // ...
        container.RegisterWebApiControllers(config);
        container.Verify();
        config.DependencyResolver = new SimpleInjectorWebApiDependencyResolver(container);
        // ...
    }
}

此外,您只需要为控制器提供一个构造函数,其中包含要注入的每个参数(删除无参数构造函数)。


关于app.CreatePerOwinContext

我会非常小心地使用这条线:

app.CreatePerOwinContext(() => container.GetInstance<AppUserManager>());

您在Owin中请求一个LifeStyle.Scoped类型的实例,但您将默认作用域声明为WebApiRequestLifestyle。这种生活方式继承自ExecutionContextScopeLifestyle,但作用域本身仅在Web Api请求开始时开始,因此我相信它不会出现在Web Api之外执行的任何中间件中(也许Steven可以帮助我们澄清这一问题)。

您可以考虑使用WebRequestLifestyle,但要注意async/await可能存在的问题。

相关内容

  • 没有找到相关文章

最新更新