2014-07-13 2 views
0

Je commence actuellement ASP.NET MVC 4 et dans le livre que je suis en train de lire, l'auteur a présenté Ninject pour l'injection de dépendance. Il a créé un résolveur de dépendance personnalisé (dont je ne comprends pas complètement le fonctionnement, mais je pense qu'il est utile de gérer facilement la résolution des dépendances).Comment ASP.NET MVC sait-il quel constructeur de contrôleur appeler?

Voici le code du contrôleur:

public class HomeController : Controller 
{ 
    private Product[] products = { 
     new Product {Name = "Kayak", Category = "Watersports", Price = 275M}, 
     new Product {Name = "Lifejacket", Category = "Watersports", Price = 48.95M}, 
     new Product {Name = "Soccer ball", Category = "Soccer", Price = 19.50M}, 
     new Product {Name = "Corner flag", Category = "Soccer", Price = 34.95M} 
    }; 

    private IValueCalculator calc; 
    public HomeController(IValueCalculator calcParam) 
    { 
     calc = calcParam; 
    } 

    public ActionResult Index() 
    { 
     ShoppingCart cart = new ShoppingCart(calc) { Products = products }; 
     decimal totalValue = cart.CalculateProductTotal(); 
     return View(totalValue); 
    } 
} 

Et le résolveur de dépendance personnalisée:

public class NinjectDependencyResolver : IDependencyResolver 
{ 
    private IKernel kernel; 
    public NinjectDependencyResolver() 
    { 
     kernel = new StandardKernel(); 
     AddBindings(); 
    } 

    public object GetService(Type serviceType) 
    { 
     return kernel.TryGet(serviceType); 
    } 

    public IEnumerable<object> GetServices(Type serviceType) 
    { 
     return kernel.GetAll(serviceType); 
    } 

    private void AddBindings() 
    { 
     kernel.Bind<IValueCalculator>().To<LinqValueCalculator>(); 
    } 
} 

Dans Application_Start(), le résolveur a été fixé:

DependencyResolver.SetResolver(new NinjectDependencyResolver()); 

Questions:

  1. Comment ASP.NET MVC a-t-il su quel constructeur de contrôleur appeler? J'ai supposé qu'il allait appeler le constructeur par défaut mais il n'y en a pas un, j'ai essayé d'en ajouter un, toujours le constructeur avec le paramètre a été appelé.

  2. Comment ASP.NET MVC a-t-il transmis IValueCalculator au constructeur?

+0

via la configuration de routage définie. –

+0

Pro ASP.NET MVC 5! – Josh

Répondre

4

C'est citation de la documentation (https://github.com/ninject/ninject/wiki/Dependency-Injection-With-Ninject):

Lorsqu'on lui a demandé d'instancier un objet, Ninject regardera constructeurs publics disponibles du type et le choisir celui qui a le plus paramètres qu'il connaît comment résoudre - ou le paramètre sans paramètre s'il y a ne sont pas appropriés (il y a un attribut qui peut être utilisé pour outrepasser ceci - voir Injection du constructeur pour le nitty gritty).

et une autre citation d'ici (https://github.com/ninject/ninject/wiki/Injection-Patterns):

Si un constructeur a un [Injecter] attribut, il est utilisé (mais si vous
appliquer l'attribut à plus d'un, Ninject sera lancer
NotSupportedException à l'exécution lors de la détection). Si aucun constructeur ne possède d'attribut [Inject], Ninject sélectionnera celui avec le plus de paramètres que Ninject comprend comment résoudre
.

Si aucun constructeur n'est défini, Ninject sélectionnera le constructeur sans paramètre par défaut (en supposant qu'il y en ait un).

Et comment ASP.NET MVC a-t-il transmis IValueCalculator au constructeur?

L'ensemble du pipeline MVC utilise des fabriques de contrôleurs pour créer une instance de contrôleur spécifique. L'usine du contrôleur utilise DependencyResolver à l'intérieur.Voilà pourquoi la dépendance résolveur est enregistré au démarrage de l'application:

DependencyResolver.SetResolver(new NinjectDependencyResolver()); 

Comme je l'ai écrit plus tôt, Ninject sait comment trouver constructeur correct et l'utilise pour construire par exemple. Il trouve ce constructeur:

public HomeController(IValueCalculator calcParam) 

Ici la dépendance résolveur est utilisé pour trouver la mise en œuvre de IValueCalculator, qui a été défini ici:

private void AddBindings() 
{ 
    kernel.Bind<IValueCalculator>().To<LinqValueCalculator>(); 
} 

Ninject tente ici un à nouveau pour trouver un constructeur pour la classe LinqValueCalculator. Si le constructeur avait des dépendances, elles seraient injectées en utilisant le même mécanisme.

+0

Donc TryGet dans Ninject essaye d'instancier le HomeController (j'ai déjà pensé que nous devions enregistrer des types sur Ninject avant de pouvoir l'instancier, comme IValueCalculator et son implémentation, est ce que je comprends bien)? Et si ce que j'ai tapé est correct, comme vous l'avez dit, Ninject essaie d'instancier en utilisant le constructeur avec la plupart des paramètres qu'il peut résoudre. Que se passe-t-il si j'ai 2 constructeurs ou plus avec le même nombre de paramètres que Ninject sait comment résoudre? Merci! –

+0

@g_b: Vous n'avez pas à enregistrer les types de classe sur lui-même. Vous devez enregistrer des interfaces. Je ne me souviens pas comment Ninject se comporte avec le même nombre de parateres dans les constructeurs. Vous devriez généralement l'éviter ou utiliser l'attribut [Inject] pour pointer le bon. – LukLed

5

Comment ASP.NET MVC savoir ...

Il sait en demandant au DependencyResolver. MVC appellera GetService() lorsqu'un contrôleur doit être créé.

Le default MVC resolver ne gère que les constructeurs de parametersless, mais dans votre cas, vous avez attribué votre résolveur personnalisé, où l'appel GetService() sera relayée à ninject de IKernel.TryGet(Type). NInject va alors chercher le type HomeController et ses constructeurs, et trouvera celui avec le paramètre IValueCalculator.

Dans la méthode AddBindings() vous avez demandé à ninject d'injecter LinqValueCalculator chaque fois qu'un IValueCalculator est nécessaire, il le fait, instancier le type en utilisant la réflexion et retourne le contrôleur initialisées à MVC.

+0

Merci, quelques questions cependant. Pourquoi a-t-il décidé d'utiliser le constructeur HomeController avec le paramètre IValueCalculator? Que faire si dans mes AddBindings, j'ai eu 2 bindings plus (IDiscountHelper, IExampleHelper) et le HomeController a encore 2 constructeurs de plus avec des paramètres simples aussi (un acceptant IDiscountHelper et l'autre constructeur acceptant IExampleHelper). Lequel choisirait-il en tant que constructeur? Aussi, pourriez-vous me diriger vers une ressource sur comment DependencyResolver fonctionne/est utilisé par ASP.NET MVC? J'ai navigué mais je n'arrive pas à en trouver un sur internet. –

Questions connexes