Ninject InSingletonScope mit Web Api RC

Ich habe einige Probleme bei der Verwendung der InSingletonScope-Bindung von Ninject mit Web Api RC. Unabhängig davon, wie ich meine Bindung erstelle, sieht es so aus, als würde Web Api Scope / Lifetime anstelle von Ninject verarbeiten.

Ich habe ein paar Variationen bei der Verkabelung von Ninject ausprobiert. Das häufigste ist identisch mit der Antwort hier:ASP.NET-Web-API-Bindung mit ninject

Ich habe auch diese Version ausprobiert:http://www.peterprovost.org/blog/2012/06/19/adding-ninject-to-web-api/

In beiden Fällen erstelle ich buchstäblich ein sofort einsatzbereites Web-API-Projekt und füge dann die Ninject-Pakete hinzu, wie in beiden Beiträgen beschrieben. Abschließend füge ich die Resolver- und Scope-Klassen hinzu, wie beispielsweise die folgende für die StackOverflow-Version:

public class NinjectDependencyScope : IDependencyScope
{
    private IResolutionRoot resolver;

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

        this.resolver = resolver;
    }

    public void Dispose()
    {
        IDisposable 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);
    }
}

und:

 public class NinjectDependencyResolver : NinjectDependencyScope, IDependencyResolver
{
    private IKernel kernel;

    public NinjectDependencyResolver(IKernel kernel)
        : base(kernel)
    {
        this.kernel = kernel;
    }
    public IDependencyScope BeginScope()
    {
        return new NinjectDependencyScope(kernel.BeginBlock());
    }
}

Dann sieht NinjectWebCommon so aus:

using System.Web.Http;
using MvcApplication2.Controllers;

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

namespace MvcApplication2.App_Start
{
    using System;
    using System.Web;

    using Microsoft.Web.Infrastructure.DynamicModuleHelper;

    using Ninject;
    using Ninject.Web.Common;

    public static class NinjectWebCommon
    {
        private static readonly Bootstrapper bootstrapper = new Bootstrapper();

        /// <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();
            kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
            kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();

            // Register Dependencies
            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)
        {
            kernel.Bind<ILogger>().To<Logger>().InSingletonScope();
        }
    }
}

Die ILogger- und Logger-Objekte tun nichts, sondern veranschaulichen das Problem. Logger führt Debug.Writeline aus, damit ich sehen kann, wann es instanziiert wurde. Und jede Aktualisierung der Seite zeigt, dass sie pro Anruf aktualisiert wird und nicht den von mir erhofften Singleton. Hier ist ein Controller, der den Logger verwendet:

public class ValuesController : ApiController
{
    private readonly ILogger _logger;
    public ValuesController(ILogger logger)
    {
        _logger = logger;
        _logger.Log("Logger created at " + System.DateTime.Now.ToLongTimeString());
    }
    // GET api/values
    public IEnumerable<string> Get()
    {
        return new string[] { "value1", "value2" };
    }
    // GET api/values/5
    public string Get(int id)
    {
        return "value";
    }
    // POST api/values
    public void Post(string value)
    {
    }
    // PUT api/values/5
    public void Put(int id, string value)
    {
    }
    // DELETE api/values/5
    public void Delete(int id)
    {
    }
}

Wenn ich Trace-Informationen in die Erstellung des Kernels einfüge, scheint dies zu zeigen, dass der Kernel nur einmal erstellt wird. Also ... was sehe ich nicht? Warum wird der Singleton nicht beibehalten?

Antworten auf die Frage(3)

Ihre Antwort auf die Frage