使用 Owin 和 Simple Injector 的 UserManager 依赖注入
UserManager dependency injection with Owin and Simple Injector
在将 Simple Injector 添加到我的项目以创建我的 UserAppManager 实例后,该实例将存在于会话的整个生命周期中,我开始收到错误:
没有无参数构造函数的错误:
An error occurred when trying to create a controller of type 'AuthController'. Make sure that the controller has a parameterless public constructor.
无参数构造函数出错:
For the container to be able to create AuthController it should have only one public constructor: it has 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);
}
}
授权控制器:
[RoutePrefix("api/auth")]
public class AuthController : ApiController
{
readonly private AppUserManager _appUserManager;
public AuthController(AppUserManager appUserManager)
{
_appUserManager = appUserManager;
}
}
依赖配置:
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>());
}
}
查看您的代码:
Startup.cs
app.UseWebApi(httpConfig);
依赖配置
container.RegisterWebApiControllers(GlobalConfiguration.Configuration);
container.Verify();
GlobalConfiguration.Configuration.DependencyResolver = new SimpleInjectorWebApiDependencyResolver(container);
我很清楚您没有为 Web Api 配置和 SimpleInjector 注册使用相同的 HttpConfiguration
实例。
请注意 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 [=57= 之外执行的任何中间件中] (也许史蒂文可以帮助我们澄清这件事)。
您可以考虑使用 WebRequestLifestyle
、but be aware of the possible issues with async/await。
在将 Simple Injector 添加到我的项目以创建我的 UserAppManager 实例后,该实例将存在于会话的整个生命周期中,我开始收到错误:
没有无参数构造函数的错误:
An error occurred when trying to create a controller of type 'AuthController'. Make sure that the controller has a parameterless public constructor.
无参数构造函数出错:
For the container to be able to create AuthController it should have only one public constructor: it has 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);
}
}
授权控制器:
[RoutePrefix("api/auth")]
public class AuthController : ApiController
{
readonly private AppUserManager _appUserManager;
public AuthController(AppUserManager appUserManager)
{
_appUserManager = appUserManager;
}
}
依赖配置:
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>());
}
}
查看您的代码:
Startup.cs
app.UseWebApi(httpConfig);
依赖配置
container.RegisterWebApiControllers(GlobalConfiguration.Configuration);
container.Verify();
GlobalConfiguration.Configuration.DependencyResolver = new SimpleInjectorWebApiDependencyResolver(container);
我很清楚您没有为 Web Api 配置和 SimpleInjector 注册使用相同的 HttpConfiguration
实例。
请注意 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 [=57= 之外执行的任何中间件中] (也许史蒂文可以帮助我们澄清这件事)。
您可以考虑使用 WebRequestLifestyle
、but be aware of the possible issues with async/await。