C# 单例作用域绑定未按预期工作

C# 单例作用域绑定未按预期工作,c#,ninject,asp.net-web-api,C#,Ninject,Asp.net Web Api,我将ninject mvc3插件用于我的web api应用程序。我有一个像这样的绑定: kernel.Bind().To().InSingletonScope() 我的解释是,内核将创建一个Foo的实例,并适当地重用它。通过在Foo的构造函数中放置断点,我可以清楚地看到每个请求调用一次断点,我无法解释原因 我唯一的猜测是,不知何故,每个请求都会创建一个新内核,但事实并非如此,因为设置全局依赖项解析器的CreateKernel方法在应用程序生命周期中只运行一次 我正在使用从中提取的一些代码,使ni

我将ninject mvc3插件用于我的web api应用程序。我有一个像这样的绑定:

kernel.Bind().To().InSingletonScope()

我的解释是,内核将创建一个
Foo
的实例,并适当地重用它。通过在
Foo
的构造函数中放置断点,我可以清楚地看到每个请求调用一次断点,我无法解释原因

我唯一的猜测是,不知何故,每个请求都会创建一个新内核,但事实并非如此,因为设置全局依赖项解析器的
CreateKernel
方法在应用程序生命周期中只运行一次

我正在使用从中提取的一些代码,使ninject在MVC4中运行良好。由于框架的变化,我不得不制作一个额外的包装器,分配给
GlobalConfiguration.Configuration.DependencyResolver

public class NinjectResolver : NinjectScope, IDependencyResolver
{
    private readonly IKernel _kernel;
    public NinjectResolver(IKernel kernel)
        : base(kernel)
    {
        _kernel = kernel;
    }
    public IDependencyScope BeginScope()
    {
        return new NinjectScope(_kernel.BeginBlock());
    }
}

我做错了什么?

注意:我用nuget安装了ninject&ninject.web.mvc(我相信你也这么做了)

我看不到您代码的其余部分,但下面是我在“NinjectDependencyScope”类中看到的内容。(我认为您的代码名为NinjectScope,可能与代码中的其他命名不一致)

public类NinjectDependencyScope:IDependencyScope
{
专用IResolutionRoot\u解析器;
内部NinjectDependencyScope(IResolutionRoot解析器)
{
Assert(解析器!=null);
_分解器=分解器;
}
#区域IDependencyScope成员
公共空间处置()
{
var disposable=_解析器作为IDisposable;
if(一次性!=null)
一次性的,一次性的;
_解析器=空;
}
公共对象GetService(类型serviceType)
{
if(_解析器==null)
抛出新的ObjectDisposedException(“此”、“此范围已被处置”);
返回_解析器.TryGet(服务类型);
}
公共IEnumerable GetServices(类型serviceType)
{
if(_解析器==null)
抛出新的ObjectDisposedException(“此”、“此范围已被处置”);
返回_resolver.GetAll(serviceType);
}
#端区
}
这是我的NinjectWebCommon类(位于App_开始文件夹中):

使用系统;
使用System.Web;
使用System.Web.Http;
使用Microsoft.Web.Infrastructure.DynamicModuleHelper;
使用Ninject;
使用Ninject.Modules;
使用Ninject.Web.Common;
[assembly:WebActivator.PreApplicationStartMethod(typeof(ABCD.Project.Web.App_Start.NinjectWebCommon),“Start”)]
[程序集:WebActivator.ApplicationShutdownMethodAttribute(typeof(ABCD.Project.Web.App_Start.NinjectWebCommon),“停止”)]
命名空间ABCD.Project.Web.App\u开始
{
公共静态类NinjectWebCommon
{
私有静态只读引导程序Bootstrap=new Bootstrapper();
/// 
///启动应用程序
/// 
公共静态void Start()
{
RegisterModule(typeof(OnePerRequestHttpModule));
RegisterModule(typeof(NinjectHttpModule));
初始化(CreateKernel);
}
/// 
///停止应用程序。
/// 
公共静态无效停止()
{
Bootstrap.ShutDown();
}
/// 
///创建将管理应用程序的内核。
/// 
///创建的内核。
私有静态IKernel CreateKernel()
{
var kernel=新的标准内核();
kernel.Bind().ToMethod(ctx=>()=>newbootstrapper().kernel);
kernel.Bind().To();
注册服务(内核);
//设置Web API解析器
GlobalConfiguration.Configuration.DependencyResolver=新的NinjectDependencyResolver(内核);
返回内核;
}
/// 
///在这里加载您的模块或注册您的服务!
/// 
///内核。
私有静态无效注册服务(IKernel内核)
{
//var modules=new-InjectModule[]{new-NinjectBindingModule(),};
//内核加载(模块);
在这里,您可以手动加载模块或定义绑定。。。
}        
}
}

我一直无法让它正常工作,我也不知道为什么。我猜这与MVC4集成目前有点不成熟有关

作为替代方案,我使用:

kernel.Bind().ToConstant(新的Foo())


这似乎有效,但我对它不太满意。

如前所述,它看起来确实像一个bug。
一种选择是自己实现一个单例扩展方法:

公共静态类NinjectSingletonExtension
{
公共静态CustomSingletonKernelModelSingletonBind(此IKernel i_KernelInstance)
{
返回新的CustomSingletonKernelModel(i_KernelInstance);
}
}
公共类CustomSingletonKernelModel
{
私有常量字符串k_ConstantInjectionName=“实现”;
私有只读IKernel_内核;
私有静态对象挂锁=新对象();
私有T_实例;
公共定制单一内核模型(IKernel i_KernelInstance)
{
这个。_kernel=i_KernelInstance;
}
公共IBindingInNamedWithOrOnSyntax To(TImplement i_常量=null),其中TImplement:class,T
{
_kernel.Bind().To().Named(k_ConstantInjectionName);
var toReturn=
_kernel.Bind().ToMethod(x=>
{
if(i_常量!=null)
{
返回i_常数;
}
如果(_concreteInstance==null)
{
锁(挂锁)
{
如果(_concreteInstance==null)
{
_混凝土实例
public class NinjectDependencyScope : IDependencyScope
{
    private IResolutionRoot _resolver;

    internal NinjectDependencyScope(IResolutionRoot resolver)
    {
        Contract.Assert(resolver != null);

        _resolver = resolver;
    }

    #region IDependencyScope Members

    public void Dispose()
    {
        var disposable = _resolver as IDisposable;
        if (disposable != null)
            disposable.Dispose();

        _resolver = null;
    }

    public object GetService(Type serviceType)
    {
        if (_resolver == null)
            throw new ObjectDisposedException("this", "This scope has already been disposed");
        return _resolver.TryGet(serviceType);
    }

    public IEnumerable<object> GetServices(Type serviceType)
    {
        if (_resolver == null)
            throw new ObjectDisposedException("this", "This scope has already been disposed");

        return _resolver.GetAll(serviceType);
    }

    #endregion
}
using System;
using System.Web;
using System.Web.Http;
using Microsoft.Web.Infrastructure.DynamicModuleHelper;
using Ninject;
using Ninject.Modules;
using Ninject.Web.Common;

[assembly: WebActivator.PreApplicationStartMethod(typeof(ABCD.Project.Web.App_Start.NinjectWebCommon), "Start")]
[assembly: WebActivator.ApplicationShutdownMethodAttribute(typeof(ABCD.Project.Web.App_Start.NinjectWebCommon), "Stop")]

namespace ABCD.Project.Web.App_Start
{
public static class NinjectWebCommon 
{
    private static readonly Bootstrapper Bootstrap = new Bootstrapper();

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

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

    /// <summary>
    /// Creates the kernel that will manage your application.
    /// </summary>
    /// <returns>The created kernel.</returns>
    private static IKernel CreateKernel()
    {
        var kernel = new StandardKernel();
        kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
        kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();

        RegisterServices(kernel);

        // Set Web API Resolver
        GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(kernel);
        return kernel;
    }

    /// <summary>
    /// Load your modules or register your services here!
    /// </summary>
    /// <param name="kernel">The kernel.</param>
    private static void RegisterServices(IKernel kernel)
    {
        //var modules = new INinjectModule[] { new NinjectBindingModule(), };
        //kernel.Load(modules);
        Here's where you would load your modules or define your bindings manually...
    }        
}
}
i_Kernel.SingletonBind<T>().To<TImplement>();
i_Kernel.Bind<T>().To<TImplement>().InSingletonScope();
var kernel = new StandardKernel();
...
kernel.Bind<Foo>().ToSelf().InSingletonScope();
kernel.Bind<IFoo>().ToMethod(context => context.Kernel.Get<Foo>());
...

// Controllers ask for the dependency as usual...
public class SomeController : ApiController
{
    readonly IFoo _foo;

    public SomeController(IFoo foo)
    {
        _foo = foo;
    }
...