2012-10-08 8 views
9

Używam ninject mvc3 plugin z moją aplikacją web api. Mam wiążący, który wygląda tak:Wiązanie pojedynczej wiązki nie działa zgodnie z przeznaczeniem

kernel.Bind<IFoo>().To<Foo>().InSingletonScope();

To jest moja interpretacja, że ​​kernal stworzy dokładnie jedną instancję Foo i używać go w odpowiedni sposób. Umieszczając punkt przerwania w konstruktorze Foo, wyraźnie widzę, że jest on wywoływany raz na żądanie i nie mogę wyjaśnić, dlaczego.

Przypuszczam, że w jakiś sposób powstaje nowe jądro dla każdego żądania, ale tak się nie dzieje, ponieważ metoda CreateKernel, która ustawia globalny program rozstrzygający zależności, jest uruchamiana tylko raz w czasie życia aplikacji.

używam jakiś kod zaczerpnięty z this post aby ninject grać ładny z MVC 4. Ze względu na zmiany ramowych, musiałem dokonać dodatkowego opakowania, które przypisać do 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()); 
    } 
} 

Co robię źle?

+2

Może nie związane Problem captncraiga, ale związany z tytułem. Miałem ten sam problem i okazało się, że przypadkowo wstrzyknąłem implementację do jednego z moich obiektów, a nie interfejsu. Tak więc w konstruktorze przypadkowo umieściłem Foo zamiast IFoo. Mam nadzieję, że to komuś pomaga ... –

Odpowiedz

5

nigdy nie mogłem dostać to działa poprawnie i nie jestem pewien dlaczego. Zgaduję, że ma to coś wspólnego z integracją MVC4, która jest w tej chwili nieco niedojrzała.

Jako alternatywę używam:

kernel.Bind<IFoo>().ToConstant(new Foo());

To wydaje się działać, ale nie jestem zbyt zadowolony z niego.

+1

http://stackoverflow.com/questions/11356864/ninject-insingletonscope-with-web-api-rc – BlakeH

1

Uwaga: Użyłem nuget do zainstalowania ninject & ninject.web.mvc (co na pewno zrobiłeś również).

Nie widzę reszty kodu, ale oto, co miałem w mojej klasie "NinjectDependencyScope". (Myślę, że twój jest nazywany po prostu NinjectScope, może być kilka innych nieścisłości nazewnictwa z kodem)

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 
} 

I tu jest moja klasa NinjectWebCommon (znajduje się w folderze App_Start):

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... 
    }   
} 
} 
+0

Mój kontroler wymaga 'IBar', który pobiera' IFoo' w konstruktorze. – captncraig

+0

Niedźwiedź ze mną, gdy wrócę do prędkości w mojej starej aplikacji internetowej MVC 4, która używała ninja ... Twój kod wygląda trochę znajomo, co zrobiłem ... – BlakeH

+0

Myślę, że może dzieje się coś dziwnego. Twój kod wygląda bardzo podobnie do mojego, poza tym, że używasz '_resolver.TryGet' i używałem' _resolver.Resolve'. Metody 'TryGet' nie istnieją w mojej wersji' IResolutionRoot'. Czy używasz wtyczki mvc3? – captncraig

3

Jak wcześniej wspomniano, wygląda jak błąd.
Jedną z opcji jest po prostu zaimplementować singleton metodę rozszerzenia siebie:

public static class NinjectSingletonExtension 
{ 
    public static CustomSingletonKernelModel<T> SingletonBind<T>(this IKernel i_KernelInstance) 
    { 
     return new CustomSingletonKernelModel<T>(i_KernelInstance); 
    } 
} 

public class CustomSingletonKernelModel<T> 
{ 
    private const string k_ConstantInjectionName = "Implementation"; 
    private readonly IKernel _kernel; 
private static object padlock = new Object(); 

    private T _concreteInstance; 


    public CustomSingletonKernelModel(IKernel i_KernelInstance) 
    { 
     this._kernel = i_KernelInstance; 
    } 

    public IBindingInNamedWithOrOnSyntax<T> To<TImplement>(TImplement i_Constant = null) where TImplement : class, T 
    { 
     _kernel.Bind<T>().To<TImplement>().Named(k_ConstantInjectionName); 
     var toReturn = 
      _kernel.Bind<T>().ToMethod(x => 
             { 
              if (i_Constant != null) 
              { 
               return i_Constant; 
              } 

              if (_concreteInstance == null) 
         { 
         lock (padlock) 
         { 
         if (_concreteInstance == null) 
         { 
          _concreteInstance = _kernel.Get<T>(k_ConstantInjectionName); 
         } 
          } 
         } 


              return _concreteInstance; 
             }).When(x => true); 

     return toReturn; 
    } 
} 

a następnie po prostu użyć:

i_Kernel.SingletonBind<T>().To<TImplement>(); 

, a następnie

i_Kernel.Bind<T>().To<TImplement>().InSingletonScope(); 


3

pewnością spóźnienie do tego wątku, ale to tylko zdarzyło mi się z usługą Windows hosting OWIN kontrolerów Web API i rozwiązywania zależności z Ninject, InSingletonScope() nie działa aż zrobiłem następujące:

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; 
    } 
... 

nadzieję, że to pomaga

+0

dzięki to rozwiązać mój problem, również z kontrolerami WebAPI, jeśli ktoś ma jasne wyjaśnienie, dlaczego .. jestem zainteresowany ! – bAN

Powiązane problemy