Domanda

Sto progettando il sito di medie dimensioni utilizzando la tecnologia mvc asp.net. Tutta la logica di business è organizzato in iServices (come IDomainService, IUserService, IAuthService, ITrainingService). Tutti i servizi stanno usando IRepositories. Sto utilizzando Ninject 1.5 per collegare i servizi con i controller e sembra perfettamente funzionante.

Non c'è finora un soggetto non ho idea di come gestire. Alcuni servizi creano contesti (per richiesta) - per esempio IDomainService crea DomainContext (per richiesta) che è necessaria per IUserService. ITrainingService viene utilizzato solo in TrainingController, che è accessibile solo dagli utenti autorizzati, e ITrainingService richiede UserContext (anche per richiesta) per sapere che sta avendo una formazione.

Questo è il mio primo progetto con contenitore CIO. C'è un modello di progettazione o il codice-schema come risolverlo? Credo di poter riempire oggetto di contesto usando ActionFilters ma come gestire la loro vita e dove mettere loro di essere accessibile per iServices? (In modo ellegant)

È stato utile?

Soluzione

Ho usato Ninject specificamente in un'applicazione MVC. Il modo in cui si sarebbe realizzare questo con Ninject è nella configurazione o vincolante delle vostre dipendenze. Quando si esegue questa operazione, specificare come si desidera che le vite degli oggetti da gestire. Nella maggior parte dei casi di una web app, voi oggetti saranno per richiesta come hai indicato nella sua interrogazione.

Una cosa che ho notato nella tua domanda è che il DomainContext che viene creato da un IDomainService oggetto e viene utilizzato da altri oggetti. Se l'oggetto del servizio di dominio è una sorta di fabbrica per una DomainContext , allora non c'è bisogno tanto di un problema - questo diventa un esercizio di come si configura Ninject per fornire oggetti concreti e iniettare le dipendenze.

Ecco un orientamento generale su come si dovrebbe strutturare la vostra applicazione - tenere a mente che non ho piena comprensione delle interfacce e classi:

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

Nota sopra che il modo più semplice per ottenere Ninject di lavorare è quello di derivare la classe applicazione dal NinjectHttpApplication di classe. Sarà necessario modificare il RegisterRoutes a un metodo di sostituzione e sarà anche necessario per implementare un metodo chiamato CreateKernel . Il CreateKernel metodo è responsabile della restituzione del kernel Ninject che è essa stessa il contenitore CIO.

Nel CreateKernel metodo , il Ninject-disponibile AutoControllerModule assiemi scansioni per classi controller MVC e li registra con il contenitore. Ciò significa che le dipendenze su tali regolatori possono essere iniettati da Ninject come è diventato il fornitore controller per l'applicazione. Il ServiceModule di classe è uno che è necessario creare per registrare tutti i servizi con Ninject. Sto indovinando che sarebbe simile a questa:

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 ha un interfaccia fluida abbastanza espressiva per la configurazione. Si noti che sopra ogni dichiarazione associa fondamentalmente una classe concreta con un'interfaccia implementa. La frase "Utilizzo" nella dichiarazione indica al kernel Ninject che l'oggetto vivrà per la vita della sola richiesta. Così, per esempio, questo significa che ogni volta che un IDomainService oggetto è richiesto dal kernel Ninject durante la stessa richiesta, verrà restituito lo stesso oggetto.

Per quanto riguarda voi contesto oggetti, mi sto prendendo una pugnalata che il vostro servizio di dominio crea questi contesti e agisce come una fabbrica di sorta. A tal proposito, ho legato le istanze DomainContext di sopra delle classi da produrre da ottenere il valore della una proprietà chiamata CurrentDomainContext off IDomainService . Questo è ciò che la lambda sopra compie. La cosa bella del "ToMethod" vincolante Ninject è che si ha accesso a un contesto di attivazione oggetto Ninject che permette di risolvere gli oggetti utilizzando il kernel. Questo è esattamente quello che facciamo al fine di ottenere il contesto di dominio corrente.

I passi successivi sono per assicurare gli oggetti accettano dipendenze correttamente. Per esempio, si dice che ITrainingService viene utilizzato solo nel TrainingController di classe. Così, in quel caso avrei garantire che TrainingController ha un costruttore che accetta un ITrainingService parametro. In quel costruttore, è possibile salvare il riferimento al ITrainingService in una variabile membro. Come in:

public class TrainingController : Controller {
  private readonly ITrainingService trainingService;

  public TrainingController(ITrainingService trainingService) {
    this.trainingService = trainingService;
  }

  // ... rest of controller implementation ...
}

Ricordate che Ninject ha già registrato tutti i controller con il kernel Ninject, in modo che quando si crea questo controller ed è vengono richiamate le azioni, avrete un riferimento al ITrainingService per mezzo del variabile membro TrainingContatti.

Spero che questo ti aiuta. Utilizzando contenitori IoC può diventare molto confuso, a volte. Nota, mi raccomando di controllare il Ninject dOCUMENTAZIONE - è un'introduzione molto ben scritto a Ninject così come concetti DI / CIO. Ho anche lasciato fuori discussione del AutoWiringModule sopra indicato; tuttavia, Nate Kohari (creatore del Ninject) ha una buona write-up sul suo blog su questa funzione.

In bocca al lupo!

Altri suggerimenti

Im non esattamente sicuro se ho capito il problema completamente, speriamo che questo po 'di consigli può aiutare.

Quando si utilizza un contenitore CIO si lascia la maniglia contenitore di oggetti di vita managment. Ho usato solo il Castello di Windsor e StructureMap per l'iniezione di dipendenza così non posso darvi un esempio concreto di come fare questo con Ninject.

Guardando attraverso la documentazione Ninject Penso che si desidera guardare attivazione Comportamenti per specificare la gestione degli oggetti di vita.

Spero che questo aiuti.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top