【发布时间】:2014-12-04 20:57:11
【问题描述】:
我们正在尝试在带有 WebAPI 管道的 Owin 中使用 Ninject。我们根据this documentation 进行了所有设置,但我们无法让 InRequestScope() 工作。
这是 startup.cs 的重要部分
public class Startup
{
public void Configuration(IAppBuilder app)
{
HttpConfiguration config = new HttpConfiguration();
// Web API routes
config.MapHttpAttributeRoutes();
// Ninject Setup
app.UseNinjectMiddleware(NinjectConfig.CreateKernel);
app.UseNinjectWebApi(config);
}
}
NinjectConfig 看起来像这样:
public sealed class NinjectConfig
{
public static IKernel CreateKernel()
{
var kernel = new StandardKernel();
INinjectModule[] modules =
{
new ApplicationModule()
};
instance.Load(modules);
// Do we still need to do this wtih Owin?
instance.Bind<IHttpModule>().To<OnePerRequestHttpModule>();
}
}
我们的 ApplicationModule 位于一个单独的基础架构项目中,可以访问我们所有不同的层,用于处理 DI 和映射:
public class ApplicationModule: NinjectModule
{
public override void Load()
{
// IUnitOfWork / EF Setups
Bind<ApplicationContext>().ToSelf().InRequestScope();
Bind<IUnitOfWork>().ToMethod(ctx => ctx.Kernel.Get<ApplicationContext>()});
Bind<ApplicationContext>().ToMethod(ctx => ctx.Kernel.Get<ChromLimsContext>()}).WhenInjectedInto<IDal>();
// other bindings for dals and business objects, etc.
}
}
然后我们有几个接口:
public interface IUnitOfWork()
{
void SaveChanges();
Task SaveChangesAsync();
}
和
public interface IDal()
{
// Crud operations, Sync and Async
}
然后我们的实际类使用这些:
public class SomeBusinessObject
{
private IUnitOfWork _uow;
private IDal _someDal;
public SomeBusinessObject(IUnitOfWork uow, IDal someDal)
{
_uow = uow;
_someDal = someDal;
}
public Task<SomeResult> SaveSomething(Something something)
{
_someDal.Save(something);
_uow.SaveChanges();
}
}
一些木豆
public class SomeDal : IDal {
private ApplicationContext _applicationContext;
public SomeDal(ApplicationContext applicationContext)
{
_applicationContext = applicationContext;
}
public void Save(Something something)
{
_applicationContext.Somethings.Add(something);
}
}
我们的 EF DbContext
public class ApplicationContext : DbContext, IUnitOfWork
{
// EF DBSet Definitions
public void SaveChanges()
{
base.SaveChanges();
}
}
期望对于每个请求,都会创建一个 ApplicationContext 实例,并将其作为 IUnitOfWork 实现注入到业务对象中,并作为 ApplicationContext 注入到 IDals 中。
相反,正在为每个使用它的类创建一个新的 ApplicationContext 实例。如果我将范围从 InRequestScope 切换到 InSingletonScope,那么(如预期的那样)为整个应用程序创建了一个实例,并正确地注入到指定的类中。既然这样可行,我假设这不是绑定问题,而是 InRequestScope 扩展的问题。
我能找到的与我遇到的类似的唯一问题是this one,但不幸的是,该解决方案不起作用。我已经引用了他在 WebApi 和 Infrastructure 项目中指定的所有包,我仔细检查以确保它们被复制到构建目录。
我做错了什么?
编辑: 一些额外的信息。查看 Ninject.Web.WebApi.OwinHost 和 Ninject.Web.Common.OwinHost 中的 Ninject 源代码,似乎 Owin 中间件将 OwinWebApiRequestScopeProvider 添加为 IWebApiRequestScopeProvider。然后在 InRequestScope() 扩展方法中使用此提供程序以返回名为“Ninject_WebApiScope”的命名范围。这将一直存在,直到被注入开关的目标类。然后命名的范围消失,并创建一个新的范围。我认为这可能是@BatteryBackupUnit 在他们的评论中所指的,但我不知道如何纠正它。
【问题讨论】:
-
我猜是你的第二个
Bind<ApplicationContext>()导致了这个。您没有将其设置为InRequestScope() -
不幸的是,这不起作用。我也试过只将 ApplicationContext 绑定到 InRequestScope 本身,然后只绑定 IUnitOfWork ToMethod(ctx => ctx.Kernel.Get
()).InRequestScope() -
.InRequestScope()是否适用于 any 绑定?存在与 ninject nuget 包安装/升级相关的“已知”问题,其中未正确设置,并且未正确注册 Request-Scope 特定的 ninject 内容。.InRequestScope()没有效果 - 遗憾的是甚至没有抛出异常。 -
@BatteryBackupUnit 这是个好问题。不幸的是,我们所做的一切都是通过 Owin 管道进行的,因此 InRequestScope 的所有行为似乎都是一致的,也就是说它们没有按预期工作。
-
我也看到过同样的行为。看起来 InRequestScope 在下面使用了一些 NamedScope 的东西。似乎正在发生的事情是它使用了一个名为“Ninject_WebApiScope”之类的范围,但是当它试图获取该范围时,它会抛出一个
UnknownScopeException,这意味着它返回一个具有瞬态范围效果的空范围对象。应该在 WebApi 调用 BeginScope 时创建该命名范围,但由于某种原因它似乎不起作用。
标签: c# entity-framework asp.net-web-api ninject owin