InRequestScope 的作用类似于 InTransientScope

Chr*_*lsh 6 c# asp.net ninject

我有一个 ASP.NET Web 应用程序(.NET Framework 4.8),我在其中设置了 NInject,但是我设置的任何服务InRequestScope都像瞬态范围一样通过(即为依赖于依赖的每个实体创建新实例)它 - 在同一个网络请求中)。

我使用的 NuGet 包如下(最新):

  1. Ninject v3.3.4
  2. Ninject.Web.Common v.3.32(“Web 项目的引导程序”)

App_Start\Ninject.Web.Common.cs 存在且正确,如下所示:

[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(ScormWebService.App_Start.NinjectWebCommon), "Start")]
[assembly: WebActivatorEx.ApplicationShutdownMethod(typeof(ScormWebService.App_Start.NinjectWebCommon), "Stop")]

namespace ScormWebService.App_Start
{
    using Microsoft.Web.Infrastructure.DynamicModuleHelper;
    using Ninject;
    using Ninject.Web.Common;
    using Ninject.Web.Common.WebHost;
    using Services;
    using System;
    using System.Web;

    public static class NinjectWebCommon
    {
        private static readonly Bootstrapper bootstrapper = new Bootstrapper();
        public static IKernel Kernel { get; private set; }

        /// <summary>
        /// Starts the application
        /// </summary>
        public static void Start()
        {
            DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
            DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
            bootstrapper.Initialize(CreateKernel);
        }

        /// <summary>
        /// Stops the application.
        /// </summary>
        public static void Stop()
        {
            bootstrapper.ShutDown();
        }

        /// <summary>
        /// Creates the kernel that will manage your application.
        /// </summary>
        /// <returns>The created kernel.</returns>
        private static IKernel CreateKernel()
        {
            var kernel = new StandardKernel();
            try
            {
                RegisterServices(kernel);
                return kernel;
            }
            catch
            {
                kernel.Dispose();
                throw;
            }
        }

        /// <summary>
        /// Load your modules or register your services here!
        /// </summary>
        /// <param name="kernel">The kernel</param>
        private static void RegisterServices(IKernel kernel)
        {
            kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
            kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
            kernel.Bind<IDumpConfigService>().To<DumpConfigService>().InSingletonScope();

            // These objects are created fresh for each request
            kernel.Bind<ILogService>().To<LogService>().InRequestScope();
            kernel.Bind<IDumpService>().To<DumpService>().InRequestScope();
            kernel.Bind<ISaveDataRequestReader>().To<SaveDataRequestReaderXml>().InRequestScope();
            kernel.Bind<ISaveDataResponseWriter>().To<SaveDataResponseWriterXml>().InRequestScope();
            kernel.Bind<IHttpContextAccessor>().To<HttpContextAccessor>().InRequestScope();

            Kernel = kernel;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

传入的请求实际上是IHttpHandler(即 ashx 而不是 aspx 文件)的实现。但是,它仍然是具有当前请求和 HttpContext.Current 的页面请求。

这是我为页面请求设置实体的方法

public class SaveDataHandler : IHttpHandler, IRequiresSessionState
{
    /// <summary>
    /// A new handler is required for each and every incoming request
    /// </summary>
    public bool IsReusable => false;

    public SaveDataHandler()
    {
        var kernel = App_Start.NinjectWebCommon.Kernel;
        LogService = (ILogService)kernel.GetService(typeof(ILogService));
        Reader = (ISaveDataRequestReader)kernel.GetService(typeof(ISaveDataRequestReader));
        Writer = (ISaveDataResponseWriter)kernel.GetService(typeof(ISaveDataResponseWriter));
        DumpService = (IDumpService)kernel.GetService(typeof(IDumpService));
    }

}
Run Code Online (Sandbox Code Playgroud)

因此,例如,ILogServiceSaveDataHandler构造函数期间为每个请求创建三个实例而不是一个: SaveDataHandler它本身请求它(见上文),就像class DumpService : IDumpService和 一样class SaveDataRequestReaderXml : ISaveDataRequestReader

任何人都可以提供有关为什么InRequestScope行为像瞬态范围的见解吗?我怀疑原因是使用IHttpHandler(ashx) 而不是 Web Form (aspx) 页面,但我不明白为什么这HttpContext.Current在整个请求中不起作用,这就是NInject.Web.Common用作请求范围标识符的原因。 我已经创建了一个 WebForm.aspx 页面,但同样的问题也发生了,所以它不是特定于 ashx/IHttpHandler请求:

namespace ScormWebService
{
    public partial class WebForm1 : Page
    {
        protected void Page_Init(object sender, EventArgs e)
        {
            var kernel = App_Start.NinjectWebCommon.Kernel;
            var LogService = (ILogService)kernel.GetService(typeof(ILogService));
            var Reader = (ISaveDataRequestReader)kernel.GetService(typeof(ISaveDataRequestReader));
            var Writer = (ISaveDataResponseWriter)kernel.GetService(typeof(ISaveDataResponseWriter));
            var DumpService = (IDumpService)kernel.GetService(typeof(IDumpService));
            // At this point, three instances of LogService have been created.
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

编辑:我创建了一个全新的最小 ASP.NET Web 窗体项目,该项目重现了您可以在此处下载的问题,但上面的代码中已经描述了所有基本元素。

谢谢。