Asp.net mvc ASP.NET MVC如何知道调用哪个控制器构造函数?

Asp.net mvc ASP.NET MVC如何知道调用哪个控制器构造函数?,asp.net-mvc,asp.net-mvc-4,ninject,Asp.net Mvc,Asp.net Mvc 4,Ninject,我目前正在启动ASP.NETMVC4,在我正在阅读的书中,作者介绍了用于依赖注入的Ninject。他创建了一个自定义依赖项解析程序(我不完全理解它是如何工作的,但我认为它的用途是方便地管理依赖项解析) 以下是控制器代码: public class HomeController : Controller { private Product[] products = { new Product {Name = "Kayak", Category = "Watersports"

我目前正在启动ASP.NETMVC4,在我正在阅读的书中,作者介绍了用于依赖注入的Ninject。他创建了一个自定义依赖项解析程序(我不完全理解它是如何工作的,但我认为它的用途是方便地管理依赖项解析)

以下是控制器代码:

public class HomeController : Controller
{
    private Product[] products = {
        new Product {Name = "Kayak", Category = "Watersports", Price = 275M},
        new Product {Name = "Lifejacket", Category = "Watersports", Price = 48.95M},
        new Product {Name = "Soccer ball", Category = "Soccer", Price = 19.50M},
        new Product {Name = "Corner flag", Category = "Soccer", Price = 34.95M}
    };

    private IValueCalculator calc;
    public HomeController(IValueCalculator calcParam)
    {
        calc = calcParam;
    }

    public ActionResult Index()
    {
        ShoppingCart cart = new ShoppingCart(calc) { Products = products };
        decimal totalValue = cart.CalculateProductTotal();
        return View(totalValue);
    }
}
和自定义依赖项解析程序:

public class NinjectDependencyResolver : IDependencyResolver
{
    private IKernel kernel;
    public NinjectDependencyResolver()
    {
        kernel = new StandardKernel();
        AddBindings();
    }

    public object GetService(Type serviceType)
    {
        return kernel.TryGet(serviceType);
    }

    public IEnumerable<object> GetServices(Type serviceType)
    {
        return kernel.GetAll(serviceType);
    }

    private void AddBindings()
    {
        kernel.Bind<IValueCalculator>().To<LinqValueCalculator>();
    }
}
问题:

  • ASP.NET MVC如何知道调用哪个控制器构造函数?我假设它将调用默认构造函数,但没有,我尝试添加了一个,但仍然调用了带有参数的构造函数

  • ASP.NET MVC是如何将IValueCalculator传递给构造函数的


  • 这是对文档()的引用:

    当要求实例化一个对象时,Ninject将查看该类型的 可用的公共构造函数,并选择具有最多 它知道如何解析参数,如果有,则为无参数参数 没有合适的(有一个属性可以用来 覆盖此项–请参阅构造函数注入以了解细节)

    还有这里的另一句话():

    如果构造函数具有[Inject]属性,则会使用它(但如果您
    将属性应用于多个,Ninject将抛出一个
    NotSupportedException在运行时检测到)

    如果没有构造函数具有[Inject]属性,Ninject将选择Ninject了解的参数最多的构造函数
    解决

    如果没有定义构造函数,Ninject将选择默认的无参数构造函数(假设有一个)

    ASP.NET MVC是如何将IValueCalculator传递给构造函数的

    整个MVC管道使用控制器工厂来构建特定控制器的实例。控制器工厂内部使用DependencyResolver。这就是在应用程序启动时注册依赖项解析程序的原因:

    DependencyResolver.SetResolver(new NinjectDependencyResolver());
    
    正如我前面所写的,Ninject知道如何找到正确的构造函数并使用它来构建实例。它发现这个构造函数:

    public HomeController(IValueCalculator calcParam)
    
    此处依赖项解析器用于查找
    IValueCalculator
    的实现,该实现在此处定义:

    private void AddBindings()
    {
        kernel.Bind<IValueCalculator>().To<LinqValueCalculator>();
    }
    
    private void AddBindings()
    {
    kernel.Bind().To();
    }
    

    Ninject在此再次尝试查找类
    LinqValueCalculator
    的构造函数。如果构造函数有依赖项,它们将使用相同的机制注入。

    这是引用文档():

    当要求实例化一个对象时,Ninject将查看该类型的 可用的公共构造函数,并选择具有最多 它知道如何解析参数,如果有,则为无参数参数 没有合适的(有一个属性可以用来 覆盖此项–请参阅构造函数注入以了解细节)

    还有这里的另一句话():

    如果构造函数具有[Inject]属性,则会使用它(但如果您
    将属性应用于多个,Ninject将抛出一个
    NotSupportedException在运行时检测到)

    如果没有构造函数具有[Inject]属性,Ninject将选择Ninject了解的参数最多的构造函数
    解决

    如果没有定义构造函数,Ninject将选择默认的无参数构造函数(假设有一个)

    ASP.NET MVC是如何将IValueCalculator传递给构造函数的

    整个MVC管道使用控制器工厂来构建特定控制器的实例。控制器工厂内部使用DependencyResolver。这就是在应用程序启动时注册依赖项解析程序的原因:

    DependencyResolver.SetResolver(new NinjectDependencyResolver());
    
    正如我前面所写的,Ninject知道如何找到正确的构造函数并使用它来构建实例。它发现这个构造函数:

    public HomeController(IValueCalculator calcParam)
    
    此处依赖项解析器用于查找
    IValueCalculator
    的实现,该实现在此处定义:

    private void AddBindings()
    {
        kernel.Bind<IValueCalculator>().To<LinqValueCalculator>();
    }
    
    private void AddBindings()
    {
    kernel.Bind().To();
    }
    
    Ninject在此再次尝试查找类
    LinqValueCalculator
    的构造函数。如果构造函数具有依赖项,则将使用相同的机制注入它们

    ASP.NET MVC是如何知道

    它通过询问
    依赖解析程序
    知道。当必须创建控制器时,MVC将调用
    GetService()

    仅处理无参数构造函数,但在您的情况下,您已经分配了自定义解析器,其中
    GetService()
    调用将中继到NInject的
    IKernel.TryGet(Type)

    NInject随后将搜索类型
    HomeController
    及其构造函数,并将找到带有
    IValueCalculator
    参数的构造函数

    AddBindings()
    方法中,您已指示NInject在每次需要
    IValueCalculator
    时注入
    LinqValueCalculator
    ,因此它会使用反射实例化类型,并将初始化的控制器返回给MVC

    ASP.NET MVC是如何知道

    它通过询问
    依赖解析程序
    知道。当必须创建控制器时,MVC将调用
    GetService()

    仅处理无参数构造函数,但在您的情况下,您已经分配了自定义解析器,其中
    GetService()
    调用将中继到NInject的
    IKernel.TryGet(Type)

    NInject随后将搜索类型
    HomeController
    及其构造函数,并将找到带有
    IValueCalculator
    参数的构造函数


    AddBindings()
    方法中,您已指示NInject在每次需要
    IValueCalculator
    时注入
    LinqValueCalculator
    ,因此它会这样做,使用反射实例化类型并将初始化的控制器返回给MVC。

    通过定义的路由配置。通过定义的路由配置。因此Ninject中的TryGet正在尝试实例化HomeController(我以前认为我们需要注册