Contrôleur de Base du constructeur d'injection dans ASP.NET MVC avec l'Unité
J'ai un contrôleur de base dans mon MVC 5 projet qui met en œuvre conjointement à la fonctionnalité. Cette fonctionnalité nécessite quelques dépendances. Je suis à l'aide de l'Unité 3 à injecter ces implémentations dans mes contrôleurs, un modèle qui a bien fonctionné jusqu'à ce que j'ai changé mon contrôleurs d'hériter de ce contrôleur de base. Maintenant, je suis en cours d'exécution dans le problème suivant:
public class BaseController : Controller
{
private readonly IService _service;
public BaseController(IService service)
{
_service = service;
}
}
public class ChildController : BaseController
{
private readonly IDifferentService _differentService;
public ChildController(IDifferentService differentService)
{
_differentService = differentService;
}
}
C'est compréhensible de lancer une erreur de 'BaseController' does not contain a constructor that takes 0 arguments
. L'unité n'est pas la résolution de la construction de la BaseController, donc il ne peut pas injecter les dépendances en elle. Je vois deux façons évidentes de la résolution de cette question:
1.) Appeler explicitement la BaseController ctor et ont chacun ChildController ctor injecter le BaseController dépendances
public class ChildController : BaseController
{
private readonly IDifferentService _differentService;
public ChildController(IDifferentService differentService,
IService baseService)
: base(baseService)
{
_differentService = differentService;
}
}
Je n'aime pas cette approche pour plusieurs raisons: premièrement, parce que le ChildControllers n'êtes pas faire usage de dépendances supplémentaires (de sorte qu'il provoque constructeur de la météorisation chez l'enfant, des contrôleurs pour aucune raison), et, plus important encore, si jamais j'ai changer la signature du constructeur du Contrôleur de Base, j'ai du modifier le constructeur de signatures de chaque enfant contrôleur.
2.) Mettre en œuvre les BaseController les dépendances via la propriété d'injection
public class BaseController : Controller
{
[Dependency]
public IService Service { get; set; }
public BaseController() { }
}
J'aime cette approche mieux - je ne suis pas à l'aide de l'une des dépendances de la BaseController du code de constructeur - mais il fait de l'injection de dépendance de la stratégie du code incompatibles, ce qui n'est pas l'idéal non plus.
Il y a probablement une bien meilleure approche qui implique une sorte de BaseController dépendance de la fonction de résolution qui appelle à l'Unité de conteneur pour le tri ctor de la signature de la méthode, mais avant de me lancer dans l'écriture de quelque chose de trop impliqué, je me demandais si quelqu'un avait résolu ce problème avant? J'ai trouvé quelques solutions qui circulent sur le web, mais ils ont des solutions de contournement comme Localisateur de Service que je ne veux pas utiliser.
Merci!
Vous devez vous connecter pour publier un commentaire.
La première chose que vous devez comprendre, c'est que vous n'êtes pas à l'instanciation de la base de contrôleur. Vous êtes l'instanciation de l'enfant contrôleur, qui hérite de la base de contrôleurs d'interface et de fonctionnalités. C'est une distinction importante. Quand vous dites "la ChildControllers n'êtes pas faire usage de dépendances supplémentaires", alors vous êtes tout à fait tort. Parce que le ChildController EST la BaseController ainsi. Il n'y a pas deux classes différentes créé. Juste une classe qui implémente les fonctionnalités.
Donc, depuis ChildController EST UN BaseController, il n'y a rien de mal ou d'étrange à propos d'un passage de paramètres dans l'enfant contrôleurs constructeur qui appelle les classes de base du constructeur. C'est la façon dont il devrait être fait.
Si vous modifiez votre classe de base, vous devrez probablement changer votre enfant des classes de toute façon. Il n'y a aucun moyen d'utilisation du constructeur d'injection pour injecter de la classe de base des dépendances qui ne sont pas inclus dans la classe enfant.
Je ne recommande pas la propriété de l'injection, car cela signifie que vos objets peuvent être créés sans l'initialisation correcte, et vous devez vous rappeler de les configurer correctement.
BTW, les termes sont sous-classe de super-classe. Un "enfant" est une sous-classe, le parent est le "super-classe".
Avec ASP.Net 5 et il est intégré dans DI
Mise à JOUR
Il y a aussi une méthode d'extension de Microsoft.Extensions.DependencyInjection pour la rendre plus
public HomeController() : this(DependencyInjectionResolver.ServiceProvider) { }
etcJ'ai pris un peu différente (mais pour moi, assez évident, et probablement commun) approche. Il fonctionne pour moi, mais il peut y avoir des pièges, je ne suis pas au courant.
J'ai créé le service commun de propriétés dans mon BaseController classe que la plupart de mes contrôleurs utilisent. Ils obtiennent instanciée lorsqu'ils sont nécessaires/référencées.
Si il y a un service à un contrôleur particulier des besoins qui est de moins en moins utilisé, je l'injecter dans le constructeur du contrôleur comme d'habitude.
Dans mon contrôleur, j'ai simplement sous-classe de cette BaseController:
De cette façon, les services communs sont générées à la volée quand ils sont nécessaires, et sont à la disposition de mes contrôleurs, sans beaucoup de passe-partout.