Asp.net mvc ASP.NET MVC如何知道调用哪个控制器构造函数?
我目前正在启动ASP.NETMVC4,在我正在阅读的书中,作者介绍了用于依赖注入的Ninject。他创建了一个自定义依赖项解析程序(我不完全理解它是如何工作的,但我认为它的用途是方便地管理依赖项解析) 以下是控制器代码: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"
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>();
}
}
问题:
这是对文档()的引用: 当要求实例化一个对象时,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(我以前认为我们需要注册