J'ai utilisé Ninject spécifiquement dans une application MVC. La façon dont vous accompliriez ceci avec Ninject est dans la configuration ou la liaison de vos dépendances. Lorsque vous faites cela, vous spécifiez comment vous souhaitez gérer les durées de vie de vos objets. Dans la plupart des cas d'une application web, vos objets seront par requête comme vous l'avez indiqué dans votre question.
Une chose que j'ai remarqué dans votre question est que votre DomainContext est créé par un objet IDomainService et est utilisé par d'autres objets. Si l'objet de service de domaine est une sorte d'usine pour un DomainContext, alors vous n'avez pas beaucoup de problème - cela devient un exercice de la façon dont vous configurez Ninject pour fournir des objets concrets et injecter des dépendances.
Voici des conseils généraux sur la façon dont vous structurer votre application - garder à l'esprit que je n'ai pas la pleine compréhension de vos interfaces et classes:
public class GlobalApplication : NinjectHttpApplication {
protected override void RegisterRoutes(RouteCollection routes) {
// Your normal route registration goes here ...
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = "" }
);
}
// This function is resposible for creating a Ninject kernel. This is where
// the magic starts to happen.
protected override IKernel CreateKernel() {
var modules = new IModule[] {
new AutoWiringModule(),
new AutoControllerModule(
Assembly.GetExecutingAssembly()),
new ServiceModule()
};
return new StandardKernel(modules);
}
}
note ci-dessus que la meilleure façon d'obtenir Ninject travailler est de dériver votre classe d'application à partir de la classe NinjectHttpApplication. Vous devrez modifier votre RegisterRoutes à une méthode de remplacement et sera également nécessaire pour implémenter une méthode appelée CreateKernel. La méthode CreateKernel est chargée de renvoyer le noyau Ninject qui est lui-même le conteneur IoC.
Dans le procédé CreateKernel, les ensembles Ninject fournis AutoControllerModule balayages pour les classes de contrôleur MVC et les enregistre avec le récipient. Cela signifie que les dépendances sur ces contrôleurs peuvent maintenant être injectées par Ninject car il est devenu le fournisseur du contrôleur pour l'application. La classe ServiceModule est celle que vous devez créer pour enregistrer tous vos services avec Ninject. Je devine qu'il ressemblerait à quelque chose comme ceci:
internal class ServiceModule : StandardModule {
public override void Load() {
Bind<IDomainService>()
.To<MyDomainService>()
.Using<OnePerRequestBehavior>();
Bind<DomainContext>()
.ToMethod(ctx => ctx.Kernel.Get<IDomainService>().CurrentDomainContext)
.Using<OnePerRequestBehavior>();
Bind<IService>()
.To<MyServiceType>()
.Using<OnePerRequestBehavior>();
}
}
Ninject a obtenu une interface de Fluent assez expressif pour la configuration. Notez ci-dessus que chaque instruction associe fondamentalement une classe concrète avec une interface qu'elle implémente. La phrase "Using" dans l'instruction indique au noyau Ninject que l'objet ne vivra que pendant la durée de la requête. Ainsi, par exemple, cela signifie qu'à chaque fois qu'un objet IDomainService est demandé au noyau Ninject lors de la même requête, le même objet sera retourné. Pour ce qui est de vos objets de contexte, je constate que votre service de domaine crée ces contextes et agit comme une sorte de fabrique. À cet égard, j'ai lié instances DomainContext classes ci-dessus à produire en obtenant la valeur d'une propriété appelée CurrentDomainContext sur le IDomainService. C'est ce que le lambda ci-dessus accomplit. La bonne chose à propos de la liaison "ToMethod" dans Ninject est que vous avez accès à un objet de contexte d'activation Ninject qui vous permet de résoudre des objets en utilisant le noyau. C'est exactement ce que nous faisons pour obtenir le contexte actuel du domaine. Les étapes suivantes consistent à s'assurer que vos objets acceptent correctement les dépendances. Par exemple, vous dites que ITrainingService est utilisé uniquement dans la classe TrainingController. Donc, dans ce cas, je m'assurerais que TrainingController a un constructeur qui accepte un paramètre ITrainingService. Dans ce constructeur, vous pouvez enregistrer la référence au ITrainingService dans une variable membre. Comme dans:
public class TrainingController : Controller {
private readonly ITrainingService trainingService;
public TrainingController(ITrainingService trainingService) {
this.trainingService = trainingService;
}
// ... rest of controller implementation ...
}
Rappelez-vous que Ninject a déjà enregistré tous vos contrôleurs avec le noyau Ninject, alors quand ce contrôleur est créé et il est des actions sont invoquées, vous aurez une référence à la ITrainingService par de la variable membre trainingService.
J'espère que cela vous aide. L'utilisation de conteneurs IoC peut parfois devenir très confuse. Notez, je vous recommande vivement de consulter le Ninject documentation - c'est une introduction très bien écrite à Ninject ainsi que des concepts DI/IoC. J'ai également laissé de côté la discussion de l'AutoWiringModule montré ci-dessus; cependant, Nate Kohari (le créateur de Ninject) a a good write-up sur son blog à propos de cette fonctionnalité.
Bonne chance!
Lien brisé, conseil largement dépassé par la réponse complète de Peter. (Un bit particulièrement faux est de suggérer des comportements d'activation (le InRequestScope dans la réponse de Peter est la bonne approche)). Suggère de supprimer cette réponse. (Pas si mal que ça, je ne suis pas loin mais pas très loin) –