“每个请求”激活上下文...没有请求

时间:2013-01-17 17:17:46

标签: c# ninject ninject.web.mvc application-start ninject.web

我有一个需要根据请求创建的存储库。现在有一个单独的缓存对象需要使用该存储库来填充数据,但是这个对象在Application_Start事件中初始化,因此没有请求上下文。

哪个是使用Ninject完成此任务的最佳方式?

感谢。

1 个答案:

答案 0 :(得分:1)

由于应用启动时缺少当前HttpContext(在IIS7集成模式下)当您尝试在app上注入依赖时,Ninject肯定会将对象绑定InRequestScope视为InTransientScope中的对象绑定启动。正如我们在Ninject的(2.2)源代码中看到的那样:

/// <summary>
/// Scope callbacks for standard scopes.
/// </summary>
public class StandardScopeCallbacks
{
    /// <summary>
    /// Gets the callback for transient scope.
    /// </summary>
    public static readonly Func<IContext, object> Transient = ctx => null;

    #if !NO_WEB
    /// <summary>
    /// Gets the callback for request scope.
    /// </summary>
    public static readonly Func<IContext, object> Request = ctx => HttpContext.Current;
    #endif
}
应用启动时

HttpContext.Current将为null,因此{app}启动时会对InRequestScope绑定对象的处理方式与绑定InTransientScope的方式相同。

所以你可以拥有global.asax

protected override Ninject.IKernel CreateKernel()
{
    var kernel = new StandardKernel();
    kernel.Bind<RequestScopeObject>().ToSelf().InRequestScope();
    kernel.Bind<SingletonScopeObject>().ToSelf().InSingletonScope();
    return kernel;
}

protected override void OnApplicationStarted()
{
    AreaRegistration.RegisterAllAreas();
    RegisterRoutes(RouteTable.Routes);
    // init cache
    this.Kernel.Get<SingletonScopeObject>().Init();
}

但是在使用RequestScopeObject之后你必须进行清理(例如Dispose(),如果它实现了IDisposable)。

public class SingletonScopeObject
{
    private string cache;
    private RequestScopeObject requestScopeObject;
    public SingletonScopeObject(RequestScopeObject requestScopeObject)
    {
        this.requestScopeObject = requestScopeObject;
    }

    public void Init()
    {
        cache = this.requestScopeObject.GetData();
        // do cleanup
        this.requestScopeObject.Dispose();
        this.requestScopeObject = null;
    }

    public string GetCache()
    {
        return cache;
    }
}

另一种方法

使用条件绑定绑定RequestScopeObject InRequestScopeInSingletonScope,如下所示:

kernel.Bind<SingletonScopeObject>()
      .ToSelf()
      .InSingletonScope()
      .Named("singletonCache");
// as singleton for initialization
kernel.Bind<RequestScopeObject>()
      .ToSelf()
      .WhenParentNamed("singletonCache")
      .InSingletonScope();
// per request scope binding
kernel.Bind<RequestScopeObject>()
      .ToSelf()
      .InRequestScope();

初始化后的清理工作保持不变。