2016-05-31 41 views
8

Ho un controller API Web con alcune risorse DI'd. Per necessità successive ho aggiunto un controller MVC, ora ho bisogno delle stesse risorse DI'd anche lì. Qui è la mia configurazione originale:Inizializzazione di Simple Injector per entrambi i controller API MVC e Web

[assembly: WebActivator.PostApplicationStartMethod(typeof(CineplexSearch.App_Start.SimpleInjectorWebApiInitializer), "Initialize")] 

namespace CineplexSearch.App_Start 
{ 
    using System.Web.Http; 
    using SimpleInjector; 
    using SimpleInjector.Integration.WebApi; 

    public static class SimpleInjectorWebApiInitializer 
    { 
     /// <summary>Initialize the container and register it as Web API Dependency Resolver.</summary> 
     public static void Initialize() 
     { 
      var container = new Container(); 
      container.Options.DefaultScopedLifestyle = new WebApiRequestLifestyle(); 

      InitializeContainer(container); 

      container.RegisterWebApiControllers(GlobalConfiguration.Configuration); 

      container.Verify(); 

      GlobalConfiguration.Configuration.DependencyResolver = 
       new SimpleInjectorWebApiDependencyResolver(container); 
     } 

     private static void InitializeContainer(Container container) 
     { 
      container.Register<ICachingManager, CachingManager>(Lifestyle.Transient); 
      container.Register<IDataAccessLayer, DataAccessLayer>(Lifestyle.Transient); 
     } 
    } 
} 

Posso registrare DI per MVC controller nello stesso posto così? Posso riutilizzare il contenitore?

Aggiornamento: Devo essere vicino, ma ora ho un errore nel controller API Web che mi serve un costruttore senza parametri; Ho provato ad aggiungere, ma poi nulla viene iniettato naturalmente

public static class SimpleInjectorWebApiInitializer 
{ 
    /// <summary>Initialize the container and register it as Web API Dependency Resolver.</summary> 
    public static void Initialize() 
    { 
     var container = new Container(); 
     container.Options.DefaultScopedLifestyle = new WebRequestLifestyle(); 

     InitializeContainer(container); 

     container.RegisterWebApiControllers(GlobalConfiguration.Configuration); 
     container.RegisterMvcControllers(Assembly.GetExecutingAssembly()); 

     container.Verify(); 

     //GlobalConfiguration.Configuration.DependencyResolver = new SimpleInjectorWebApiDependencyResolver(container); 
     DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container)); 
    } 

    private static void InitializeContainer(Container container) 
    { 
     container.Register<ICachingManager, CachingManager>(Lifestyle.Transient); 
     container.Register<IDataAccessLayer, DataAccessLayer>(Lifestyle.Transient); 
    } 
} 

risposta

10

Posso riutilizzare il contenitore?

Sì, è possibile, e si dovrebbe. In genere, ogni dominio dell'app deve avere un'istanza contenitore.

La MVC integration documentation della documentazione iniettore semplice spiega che è necessario impostare l'MVC DependencyResolver come segue:

DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container)); 

per rendere le cose più facili tuttavia, il vostro dovrebbe registrare il WebRequestLifestyle come DefaultScopedLifestyle:

container.Options.DefaultScopedLifestyle = new WebRequestLifestyle(); 

Ciò funzionerà anche per le API Web, dal momento che esegui esclusivamente API Web da IIS.

Quindi è necessario configurare sia DependencyResolvers.

+0

Grazie per la risposta rapida, ho quasi dovuto farlo funzionare, si può vedere il mio aggiornamento? – FailedUnitTest

+0

@FailedUnitTest è necessario * entrambi * i resolver di dipendenza. Quindi anche il resolver di dipendenze API Web. – Steven

+0

Questo l'ha risolto, grazie Steven! – FailedUnitTest

0

Vorrei aggiungere i miei due centesimi perché dopo aver letto la risposta di Steven e i commenti sottostanti ho ancora alcuni errori. Alla fine questo ha a che fare con l'ordine in cui le cose si stanno configurando.

protected void Application_Start() 
{ 
    //set the default scoped lifestyle 
    Container container = new Container(); 
    container.Options.DefaultScopedLifestyle = new WebRequestLifestyle(); 

    ... 
    //do class registration here. I did it with Scoped lifestyle 
    ... 
    //Let the SimpleInjector.Intergration packages register the controllers.  
    container.RegisterWebApiControllers(GlobalConfiguration.Configuration); 
    container.RegisterMvcControllers(Assembly.GetExecutingAssembly()); 

    AreaRegistration.RegisterAllAreas(); 
    //This must be here because we first need to do above before registering the web api. See WebApiConfig code. 
    GlobalConfiguration.Configure(WebApiConfig.Register); 
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); 
    RouteConfig.RegisterRoutes(RouteTable.Routes); 
    BundleConfig.RegisterBundles(BundleTable.Bundles); 

    //don't set the resolver here, do it in WebApiConfig.Register() 
    //DependencyResolver.SetResolver(new SimpleInjectorWebApiDependencyResolver(container)); 
    DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container)); 
    container.Verify(SimpleInjector.VerificationOption.VerifyAndDiagnose); 
} 

WebApiConfig:

public static class WebApiConfig 
{ 
    public static void Register(HttpConfiguration config) 
    { 
     // Web API routes 
     config.MapHttpAttributeRoutes(); 
     //set the webApi resolver here! 
     config.DependencyResolver = new SimpleInjectorWebApiDependencyResolver(DependencyInjectionCoreSetup._Container); 
     //then the rest.. 
     var route = config.Routes.MapHttpRoute(
     .... 
    } 
}