C# 如何为ASP.NET MVC 5创建依赖项注入?

C# 如何为ASP.NET MVC 5创建依赖项注入?,c#,asp.net,asp.net-mvc,dependency-injection,asp.net-mvc-5,C#,Asp.net,Asp.net Mvc,Dependency Injection,Asp.net Mvc 5,使用ASP.NET内核创建依赖项注入相当容易。文档很好地解释了这一点,这家伙有一个很好的解释 然而,我想对我的ASP.NETMVC5项目做同样的事情。如何使用ASP.MVC 5处理依赖项注入 此外,依赖项注入是否仅限于控制器,或者是否可以与任何类一起工作?在ASP.NET MVC 5中实现依赖项注入的最简单方法是使用Microsoft自己开发的工具,称为Unity 您可以在internet上找到许多关于它的资源,您可以从阅读此处提供的官方文档开始: 此外,依赖项注入是否仅限于控制器,或者是否可以

使用ASP.NET内核创建依赖项注入相当容易。文档很好地解释了这一点,这家伙有一个很好的解释

然而,我想对我的ASP.NETMVC5项目做同样的事情。如何使用ASP.MVC 5处理依赖项注入


此外,依赖项注入是否仅限于控制器,或者是否可以与任何类一起工作?

在ASP.NET MVC 5中实现依赖项注入的最简单方法是使用Microsoft自己开发的工具,称为
Unity

您可以在internet上找到许多关于它的资源,您可以从阅读此处提供的官方文档开始:

此外,依赖项注入是否仅限于控制器,或者是否可以与任何类一起工作

它适用于任何项目中的任何类,只要您注册与实现相关的接口(如果您想从中获利),那么您所要做的就是在构造函数中添加接口实例化。

我建议您使用,还有其他fwk,如unity、ninject、,基准测试autofac具有优异的性能

这是与MVC的集成(可用于所有类)


在ASP.Net MVC中,您可以使用NuGet的.Net Core DI,而不是第三方替代方案:-

using Microsoft.Extensions.DependencyInjection
对于MVC启动/配置类:-

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);
}
我的项目使用Identity User,我已经替换了OWIN启动配置,转而采用基于服务的方法。默认标识用户类使用静态工厂方法创建实例。我已经将代码移动到构造函数中,并依赖DI提供适当的注入。这项工作仍在进行中,但我的工作如下:-

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)));
}
public void配置服务(IServiceCollection服务)
{               
//====================================================
//为标识数据库创建数据库上下文
//====================================================
//添加数据库上下文-可以不使用任何参数进行实例化
AddTransient(typeof(ApplicationDbContext));
//====================================================
//应用程序服务器管理器
//====================================================
//实例化需要标识数据库的以下实例
AddTransient(typeof(IUserStore),p=>newuserstore(newapplicationdbcontext());
//通过上述定义,我们可以将user manager类添加为一个类型
AddTransient(类型为(ApplicationUserManager));
//====================================================
//应用程序签名管理器
//====================================================
//实例化需要两个参数,[ApplicationUserManager](上面定义)和[IAAuthenticationManager]
AddTransient(typeof(Microsoft.Owin.Security.iaAuthenticationManager),p=>new-OwinContext().Authentication);
AddTransient(typeof(applicationSigningManager));
//====================================================
//应用程序角色管理器
//====================================================
//将标识角色的角色管理器映射到具体的角色管理器类型
services.AddTransient();
//将角色存储角色映射到实现的类型
services.AddTransient();
AddTransient(类型为(应用程序角色管理器));
//====================================================
//将所有控制器添加为服务
//====================================================
services.addControllerAsservices(typeof(Startup).Assembly.GetExportedTypes()
.Where(t=>!t.isastract&!t.IsGenericTypeDefinition)
.Where(t=>typeof(IController).IsAssignableFrom(t)
||t.Name.EndsWith(“Controller”,StringComparison.OrdinalIgnoreCase));
}
Account Controller类具有单个构造函数:-

[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;
    }
}
[授权]
公共类AccountController:控制器
{
专用应用程序signInManager\u signInManager;
私有应用程序用户管理器\u用户管理器;
私人角色经理(RoleManager);;
公共帐户控制器(ApplicationUserManager用户管理器、ApplicationSignInManager signInManager、RoleManager RoleManager)
{
UserManager=UserManager;
SignInManager=SignInManager;
RoleManager=RoleManager;
}
}

对于这个答案,我下载了一个作为示例的基础,并在其中添加了DI服务,如下所示:

  • 将目标框架更新为4.6.1
  • NuGet DI包:-Microsoft.Extensions.DependencyInjection
在标准MapHttpRoute配置之后,添加代码以注册您需要的服务

使用

WebApiConfig

默认产品

MyDependencyResolver

//
///基于IDependencyResolver为应用程序提供默认依赖项解析器,IDependencyResolver只有两个方法。
///这是MVC和WebAPI使用的组合依赖项解析器。
/// 
公共类MyDependencyResolver:System.Web.Mvc.IDependencyResolver,System.Web.Http.Dependency.IDependencyResolver
{
受保护的IServiceProvider服务提供商;
受保护的IServiceScope范围=空;
公共MyDependencyResolver(IServiceProvider服务提供商)
{
this.serviceProvider=serviceProvider;
}
公共MyDependencyResolver(IServiceScope范围)
{
this.scope=范围;
this.serviceProvider=scope.serviceProvider;
}
公共IDependencyScope BeginScope()
{
返回新的MyDependencyResolver(serviceProvider.CreateScope());
}
公共空间处置()
{
处置(真实);
}
受保护的虚拟void Dispose(bool disposing)
{
范围?.Dispose();
}
公共对象GetService(类型serviceType)
{
返回此.serviceProvider.GetService(serviceType);
}
公共IEnumerable服务(
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;
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.
/// This is combined dependency resolver for MVC and WebAPI usage.
/// </summary>
public class MyDependencyResolver : System.Web.Mvc.IDependencyResolver, System.Web.Http.Dependencies.IDependencyResolver 
{
    protected IServiceProvider serviceProvider;
    protected IServiceScope scope = null;

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

    public MyDependencyResolver(IServiceScope scope) 
    {
        this.scope = scope;
        this.serviceProvider = scope.ServiceProvider;
    }

    public IDependencyScope BeginScope() 
    {
        return new MyDependencyResolver(serviceProvider.CreateScope());
    }

    public void Dispose() 
    {
        Dispose(true);
    }

    protected virtual void Dispose(bool disposing) 
    {
        scope?.Dispose();
    }

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

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

        return services;
    }
}
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);
        }
    }
}
/// <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);
    }
}
public class ServiceRegister : IWindsorInstaller
{
    public void Install(Castle.Windsor.IWindsorContainer container,
    Castle.MicroKernel.SubSystems.Configuration.IConfigurationStore store)
    {
        SomeTypeRequiredByConstructor context = new SomeTypeRequiredByConstructor ();

        container.Register(
            Component
                .For<IServiceToRegister>()
                .ImplementedBy<ServiceToRegister>().
             DependsOn(Dependency.OnValue<SomeTypeRequiredByConstructor>(context))//This is in case your service has parametrize constructoe
                .LifestyleTransient());
    }
}
public class MyController 
{
    IServiceToRegister _serviceToRegister;

    public MyController (IServiceToRegister serviceToRegister)
    {
        _serviceToRegister = serviceToRegister;//Then you can use it inside your controller
    }
}
    services.AddControllersAsServices(typeof(Startup).Assembly.GetExportedTypes()
      .Where(t => !t.IsAbstract && !t.IsGenericTypeDefinition)
      .Where(t => typeof(IController).IsAssignableFrom(t) 
       || t.Name.EndsWith("Controller", StringComparison.OrdinalIgnoreCase)));