7
votes

Injecter une dépendance dans un liant de modèle personnalisé et utiliser IndreQuestScope en utilisant Ninject

J'utilise Niject avec ninject.web.mvc.

Pour commencer, j'ai créé un simple projet de test dans lequel je veux une instance de ipostrepository code> à partager entre un contrôleur et un liant de modèle personnalisé lors de la même demande Web. Dans mon vrai projet, j'en ai besoin parce que j'obtiens IentityChangeTracker Code> lorsque je dispose efficacement de deux référentiels accédant au même graphique d'objet. Donc, pour garder mon projet de test simple, j'essaie simplement de partager un référentiel factice. P>

Le problème que je vais avoir, c'est que cela fonctionne sur la première demande et c'est tout. Le code pertinent est ci-dessous. P>

NInjectModule: P>

ModelBinders.Binders.Add(typeof(string),
    DependencyResolver.Current.GetService<CustomModelBinder>());


3 commentaires

Related: plus générale de réponse Stackoverflow.com/Questtions/2899680/...


@Rubenbartelink merci pour le lien mate. Je vais prendre cela à bord et prendre un autre regard sur ce que j'ai.


Vous êtes les bienvenus (FYI Ce ranger et ce lien est en réponse à Un DUP de cette question d'aujourd'hui )


3 Réponses :


8
votes

Les modèles sont réutilisés par MVC pour plusieurs demandes. Cela signifie qu'ils ont un cycle de vie plus long que la portée de la demande et donc ne sont donc pas autorisés à dépendre des objets avec le cycle de vie de la portée de la demande plus courte.

Utilisez un usine au lieu de créer l'ipostrepository pour chaque exécution de Bindmodel


7 commentaires

Merci pour votre réponse. Après avoir lu votre article, j'ai mis à niveau vers Ninject 3.0.0 RC3 afin d'utiliser l'extension d'usine. J'ai réussi à résoudre certains problèmes d'installation et un problème avec les symboles de débogage, mais je ne peux même plus injecter des dépendances dans mon contrôleur. Je reçois l'exception standard de constructeur sans paramètre. Après avoir exécuté des tests unitaires, j'ai confirmé que les modules sont chargés correctement, donc je suis à perte quant à ce que le problème est. J'espère que cela ne vous dérange pas, mais mon code et les deux tests sont ici: Pastebin.com/wvnqbflq


J'ai configuré une nouvelle application MVC à l'aide du modèle par défaut, a ajouté votre code et l'application s'exécute parfaitement. Êtes-vous sûr que vous avez tout mis à jour à NInject 3.0.0 à l'aide de "Install-package ninject.mvc3 -pre"?


Salut Remo, merci beaucoup de vérifier cela pour moi. Je viens de recréer mon projet ici (en veillant explicitement que les packages ont été installés avec Install-package ninject.mvc3 -pre) et je reçois maintenant une exception directement à partir de Ninject: pastebin.com/nhj3qqym serait-il possible pour vous de télécharger le projet que vous avez afin que je puisse jeter un coup d'oeil?


Peut-il être que vous déroulez de Ninjecthttpplication et utilisez app_start / ninjectwebcommons.cs en même temps?


Bah, c'était ça. J'ai oublié cela crée le dossier lorsque vous installez les paquets. Désolé pour ça. Cela fonctionne maintenant mais je ne peux toujours pas sembler partager mon instance de référentiel. J'ai lu votre article une seconde fois à nouveau et remarqua quelques choses. Cette partie en particulier: "Cela indique à NIJJECT qu'il doit mettre en œuvre automatiquement une classe d'usine pour l'interface spécifiée et injecter une nouvelle instance de cette usine dans chaque objet qui demande une instance de l'interface d'usine." Cela signifie que je ne sais toujours pas comment partager le référentiel entre le classeur et le contrôleur.


Jusqu'à présent, j'ai essayé de déplacer le usine.createpostrepository () appel à BindModel pour créer le référentiel. J'ai ensuite essayé de changer le contrôleur pour accepter une dépendance en usine pour créer également un référentiel là-bas, puis changer l'usine sur: tofactory (). IndreQuestScope () . Enfin, j'ai essayé d'utiliser paresseux mais j'ai réalisé que cela n'a pas de sens que cela remonte à ce que vous avez dit à propos du cycle de vie du liant modèle.


J'ai confirmé l'utilisation de NHProf que l'usine Ninject partage en fait une seule instance dans la demande de demande correctement.



4
votes

J'ai finalement géré pour le résoudre avec une usine comme suggérée. Cependant, je ne pouvais tout simplement pas comprendre comment accomplir cela avec ninject.extensions.factory code> ce que j'aurais préféré. Voici ce que j'ai fini avec:

l'interface d'usine: p> xxx pré>

la mise en oeuvre d'usine: p> xxx pré>

le Module NINJECT pour l'usine: P>

protected override void OnApplicationStarted()
{
    AreaRegistration.RegisterAllAreas();

    RegisterGlobalFilters(GlobalFilters.Filters);
    RegisterRoutes(RouteTable.Routes);

    ModelBinders.Binders.Add(typeof(string), kernel.Get<CustomModelBinder>());
}


0 commentaires

5
votes

C'est vraiment simple pour obtenir l'extension de l'usine Ninject et en cours d'exécution, mais cela ne me disait pas des réponses existantes.

Le plugin Extensions d'usine est une condition préalable, qui peut être installée via Nuget: p> xxx pré>

Vous avez juste besoin d'une usine injectée dans votre liant modèle quelque part, par exemple: p> xxx pré>

puis crée une interface pour l'usine. Le nom de l'usine et le nom de la méthode ne comptent pas du tout, juste le type de retour. (Bon à savoir si vous souhaitez injecter une session de NHibernate mais que vous ne voulez pas avoir à vous soucier de référencer l'espace de noms correct pour iSessionFactory code>, également utile pour savoir si getcurentrepository code> fait ce qu'il fait plus clairement en contexte): p> xxx pré>

puis, en supposant que votre ipostrepository code> est déjà géré par NIject correctement, l'extension fera tout sinon pour vous juste en appelant la méthode .Tofactory (). p> xxx pré>

alors vous appelez simplement votre méthode d'usine dans le code où vous en avez besoin: P>

var repo = _factory.CreatePostRepository();
repo.DoStuff();


1 commentaires

Merci d'avoir posté ceci. Bien que le projet soit maintenant terminé et déployé, j'apprécie vraiment que vous ajoutez cette réponse. C'est quelque chose que je vais renvoyer à l'avenir.