web-dev-qa-db-fra.com

Initialisation d'injecteur simple pour les contrôleurs MVC et Web API

J'ai un contrôleur API Web qui a des ressources DID. Par la suite, j’ai ajouté un contrôleur MVC et j’ai maintenant besoin des mêmes ressources. Voici ma configuration d'origine: 

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

Puis-je enregistrer DI pour MVC Controller au même endroit? Puis-je réutiliser le conteneur?

Mise à jour: Je dois être proche, mais je reçois maintenant une erreur dans le contrôleur de l'API Web pour laquelle j'ai besoin d'un constructeur sans paramètre. J'ai essayé de l'ajouter, mais rien ne s'injecte bien sûr

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

Puis-je réutiliser le conteneur?

Oui, vous pouvez et vous devriez. Chaque domaine d'application doit généralement avoir une instance de conteneur.

La Documentation d'intégration MVC de la documentation Simple Injector explique que vous devez définir MVC DependencyResolver comme suit:

DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container));

Cependant, pour faciliter les choses, vous devez inscrire la WebRequestLifestyle comme DefaultScopedLifestyle:

container.Options.DefaultScopedLifestyle = new WebRequestLifestyle();

Cela fonctionnera également pour l'API Web, car vous n'exécutez l'API Web qu'à partir d'IIS.

Vous devez donc configurer les deux DependencyResolvers.

12
Steven

Sachez également que la WebRequestLifestyle() est obsolète à l’époque. Vous pouvez utiliser à la place:

//...

container.Options.DefaultScopedLifestyle = new SimpleInjector.Lifestyles.AsyncScopedLifestyle();

//...
1
Bruno Mósca

Je voudrais ajouter mes deux cents parce qu'après avoir lu la réponse de Steven et les commentaires ci-dessous, il me restait quelques erreurs. Finalement, cela a à voir avec l'ordre dans lequel les choses sont en train d'être configurées.

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(
        ....
    }
}
1
CularBytes