53 votes

Comment créer une injection de dépendance pour ASP.NET MVC 5?

La création de l'Injection de Dépendance avec ASP.NET de Base est assez facile. La documentation, l'explique très bien ici, et ce gars est un tueur de la vidéo pour l'expliquer.

Cependant, je veux faire la même chose avec mon ASP.NET MVC 5 projet. Comment peut gérer l'injection de dépendance avec l'ASP.MVC 5?

Aussi, est l'injection de Dépendance limité à seulement les contrôleurs de ou cela peut-il fonctionner avec n'importe quelle classe?

41voto

pixelda Points 81

Dans ASP.Net MVC, vous pouvez utiliser le .Net de Base DI de NuGet plutôt que d'un tiers des alternatives:-

using Microsoft.Extensions.DependencyInjection

Pour le MVC Start/classe de Configuration:-

public void Configuration(IAppBuilder app)
        {
            // We will use Dependency Injection for all controllers and other classes, so we'll need a service collection
            var services = new ServiceCollection();

            // configure all of the services required for DI
            ConfigureServices(services);

            // Configure authentication
            ConfigureAuth(app);

            // Create a new resolver from our own default implementation
            var resolver = new DefaultDependencyResolver(services.BuildServiceProvider());

            // Set the application resolver to our default resolver. This comes from "System.Web.Mvc"
            //Other services may be added elsewhere through time
            DependencyResolver.SetResolver(resolver);
        }

Mon projet utilise l'Identité de l'Utilisateur et j'ai remplacé le OWIN démarrage de la configuration de suivre une approche orientée sur les services à la place. La valeur par défaut de l'Identité de l'Utilisateur classes d'utiliser des méthodes de fabrique de créer des instances. J'ai déplacé ce code dans les constructeurs et invoqué DI de fournir à la appropriée de l'injection. Il est toujours en cours, mais voici où j'en suis:-

 public void ConfigureServices(IServiceCollection services)
        {               
            //====================================================
            // Create the DB context for the IDENTITY database
            //====================================================
            // Add a database context - this can be instantiated with no parameters
            services.AddTransient(typeof(ApplicationDbContext));

            //====================================================
            // ApplicationUserManager
            //====================================================
            // instantiation requires the following instance of the Identity database
            services.AddTransient(typeof(IUserStore<ApplicationUser>), p => new UserStore<ApplicationUser>(new ApplicationDbContext()));

            // with the above defined, we can add the user manager class as a type
            services.AddTransient(typeof(ApplicationUserManager));

            //====================================================
            // ApplicationSignInManager
            //====================================================
            // instantiation requires two parameters, [ApplicationUserManager] (defined above) and [IAuthenticationManager]
            services.AddTransient(typeof(Microsoft.Owin.Security.IAuthenticationManager), p => new OwinContext().Authentication);
            services.AddTransient(typeof(ApplicationSignInManager));

            //====================================================
            // ApplicationRoleManager
            //====================================================
            // Maps the rolemanager of identity role to the concrete role manager type
            services.AddTransient<RoleManager<IdentityRole>, ApplicationRoleManager>();

            // Maps the role store role to the implemented type
            services.AddTransient<IRoleStore<IdentityRole, string>, RoleStore<IdentityRole>>();
            services.AddTransient(typeof(ApplicationRoleManager));

            //====================================================
            // Add all controllers as services
            //====================================================
            services.AddControllersAsServices(typeof(Startup).Assembly.GetExportedTypes()
                .Where(t => !t.IsAbstract && !t.IsGenericTypeDefinition)
            .Where(t => typeof(IController).IsAssignableFrom(t)
            || t.Name.EndsWith("Controller", StringComparison.OrdinalIgnoreCase)));
        }

Le Compte de Contrôleur de classe est le seul constructeur:-

[Authorize]
public class AccountController : Controller
{
    private ApplicationSignInManager _signInManager;
    private ApplicationUserManager _userManager;
    private RoleManager<IdentityRole> _roleManager;

    public AccountController(ApplicationUserManager userManager, ApplicationSignInManager signInManager, RoleManager<IdentityRole> roleManager)
    {
        UserManager = userManager;
        SignInManager = signInManager;
        RoleManager = roleManager;
    }

31voto

pixelda Points 81

Pour cette réponse, j'ai téléchargé un Exemple de Microsoft de WebApi projet comme base pour l'exemple et a ajouté DI services comme suit,

  • Mise à jour le Framework Cible à 4.6.1
  • NuGet la DI package :- Microsoft.Extensions.DependencyInjection

Après le standard MapHttpRoute de configuration, ajoutez le code pour inscrire les services dont vous avez besoin

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;

using Microsoft.Extensions.DependencyInjection;
using System.Web.Http.Dependencies;
using ProductsApp.Controllers;

namespace ProductsApp
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            // Web API routes
            config.MapHttpAttributeRoutes();

            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );


            // create the DI services and make the default resolver
            var services = new ServiceCollection();
            services.AddTransient(typeof(DefaultProduct));
            services.AddTransient(typeof(ProductsController));

            var resolver = new MyDependencyResolver(services.BuildServiceProvider());
            config.DependencyResolver = resolver;
        }
    }

    public class DefaultProduct : ProductsApp.Models.Product
    {
        public DefaultProduct()
        {
            this.Category = "Computing";
            this.Id = 999;
            this.Name = "Direct Injection";
            this.Price = 99.99M;
        }
    }

    /// <summary>
    /// Provides the default dependency resolver for the application - based on IDependencyResolver, which hhas just two methods
    /// </summary>
    public class MyDependencyResolver : IDependencyResolver
    {
        protected IServiceProvider _serviceProvider;

        public MyDependencyResolver(IServiceProvider serviceProvider)
        {
            this._serviceProvider = serviceProvider;
        }

        public IDependencyScope BeginScope()
        {
            return this;
        }

        public void Dispose()
        {

        }

        public object GetService(Type serviceType)
        {
            return this._serviceProvider.GetService(serviceType);
        }

        public IEnumerable<object> GetServices(Type serviceType)
        {
            return this._serviceProvider.GetServices(serviceType);
        }

        public void AddService()
        {

        }
    }

    public static class ServiceProviderExtensions
    {
        public static IServiceCollection AddControllersAsServices(this IServiceCollection services, IEnumerable<Type> serviceTypes)
        {
            foreach (var type in serviceTypes)
            {
                services.AddTransient(type);
            }

            return services;
        }
    }
}

J'ai ensuite modifié le contrôleur existant pour prendre la DI type (remarque il est juste l'un ctor)

using ProductsApp.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;

namespace ProductsApp.Controllers
{
    public class ProductsController : ApiController
    {
        DefaultProduct _dp = null;

        public ProductsController(DefaultProduct dp)
        {
            _dp = dp;
            //
            products.Add(dp);
        }

        List<Product> products = new List<Product>()
        {
            new Product { Id = 1, Name = "Tomato Soup", Category = "Groceries", Price = 1 },
            new Product { Id = 2, Name = "Yo-yo", Category = "Toys", Price = 3.75M },
            new Product { Id = 3, Name = "Hammer", Category = "Hardware", Price = 16.99M }
        };

        public IEnumerable<Product> GetAllProducts()
        {
            return products;
        }

        public IHttpActionResult GetProduct(int id)
        {
            var product = products.FirstOrDefault((p) => p.Id == id);
            if (product == null)
            {
                return NotFound();
            }
            return Ok(product);
        }
    }
}

5voto

pixelda Points 81

Mon résolveur de dépendance par défaut

 /// <summary>
/// Provides the default dependency resolver for the application - based on IDependencyResolver, which hhas just two methods
/// </summary>
public class DefaultDependencyResolver : IDependencyResolver
{
    /// <summary>
    /// Provides the service that holds the services
    /// </summary>
    protected IServiceProvider serviceProvider;

    /// <summary>
    /// Create the service resolver using the service provided (Direct Injection pattern)
    /// </summary>
    /// <param name="serviceProvider"></param>
    public DefaultDependencyResolver(IServiceProvider serviceProvider)
    {
        this.serviceProvider = serviceProvider;
    }

    /// <summary>
    /// Get a service by type - assume you get the first one encountered
    /// </summary>
    /// <param name="serviceType"></param>
    /// <returns></returns>
    public object GetService(Type serviceType)
    {
        return this.serviceProvider.GetService(serviceType);
    }

    /// <summary>
    /// Get all services of a type
    /// </summary>
    /// <param name="serviceType"></param>
    /// <returns></returns>
    public IEnumerable<object> GetServices(Type serviceType)
    {
        return this.serviceProvider.GetServices(serviceType);
    }
}
 

4voto

Dei Revoledo Points 125

Je vous recommande d'utiliser Autofac, il y a d'autres fwk comme unité, ninject, les points de repère autofac a excelent perfomance.

http://www.palmmedia.de/blog/2011/8/30/ioc-container-benchmark-performance-comparison

Ici, c'est l'intégration avec MVC (et travaille avec l'ensemble de la classe)

http://docs.autofac.org/en/latest/integration/mvc.html

3voto

Sakuto Points 3111

La façon la plus simple de implémente l'Injection de Dépendance dans ASP.NET MVC 5 est l'utilisation de l'outil développé par Microsoft lui-même, appelé Unity.

Vous pouvez trouver de nombreuses ressources sur internet à ce sujet, et vous pouvez commencer par lire la documentation officielle disponible ici: Guide du Développeur de l'Injection de Dépendance à l'Aide de l'Unité

Aussi, est l'injection de Dépendance limité à seulement les contrôleurs de ou cela peut-il fonctionner avec n'importe quelle classe?

Il fonctionne avec n'importe quelle classe, quel que soit le projet, aussi longtemps que vous vous inscrivez sur l'Interface liée à la mise en Œuvre (si vous voulez profiter de la Cio modèle), tout ce que vous avez à faire est d'ajouter l'Interface de l'instanciation de votre constructeur.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X