Ninject 是跟Unity 差不多的DI容器。Ninject 推荐零配置,快速使用。小中型项目,最适合。
通过nuget,安装Ninject.MVC。略。参考博客:Ninject依赖注入 WebForm中使用
场景模拟 项目下载地址:https://coding.net/u/chenxygx/p/CodeSave/git/tree/master/EssentialTools
定义一个计算产品的接口,IValueCalculator,往后都会围绕产品计算,来进行依赖注入。
namespace EssentialTools.Models
{
public interface IValueCalculator
{
decimal ValueProduct(IEnumerable<Product> products);
}
}
IValueCalculator
接下来定义产品实现,LinqValueCalculator
public class LinqValueCalculator : IValueCalculator
{
public decimal ValueProduct(IEnumerable<Product> products)
{
return products.Sum(p => p.Price);
}
}
LinqValueCalculator
Product,就是一个普通的实体类,就不贴了。
然后在控制器中,使用Ninject进行输出。
public class HomeController : Controller
{
private IValueCalculator calc;
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 flagW",Category="Soccer",Price = 34.95M }
};
// GET: Home
public ActionResult Index()
{
IKernel kernel = new StandardKernel();
kernel.Bind<IValueCalculator>().To<LinqValueCalculator>();
IValueCalculator calc = kernel.Get<IValueCalculator>();
return View(calc.ValueProduct(products));
}
}
HomeController
接下来,把Ninject跟MVC进行整合操作。首先需要添加一个Ninject依赖项解析器,NinjectDependencyResolver
public class NinjectDependencyResolver : IDependencyResolver
{
private IKernel kernel;
public NinjectDependencyResolver(IKernel kernelParam)
{
kernel = kernelParam;
AddBindings();
} private void AddBindings()
{
kernel.Bind<IValueCalculator>().To<LinqValueCalculator>();
}
public object GetService(Type serviceType)
{
return kernel.TryGet(serviceType);
} public IEnumerable<object> GetServices(Type serviceType)
{
return kernel.GetAll(serviceType);
}
}
NinjectDependencyResolver
主要作用就是在页面加载之前,进行依赖注入。然后我们将解析器与MVC关联一下。在App_Start的NinjectWebCommon里面修改
private static void RegisterServices(IKernel kernel)
{
new NinjectDependencyResolver(kernel);
}
这样,在MVC程序运行后,会首先进行依赖注入。然后就可以在需要的时候,控制反转出实例了。
接下来,实现构造器的控制反转
public class HomeController : Controller
{
private IValueCalculator calc;
public HomeController(IValueCalculator calcParam)
{
calc = calcParam;
} // GET: Home
public ActionResult Index()
{
return View(calc.ValueProduct(products));
}
}
HomeController
控制反转会考察依赖项是否依赖其他类型,例如如果LinqValueCalculator,还有依赖项,则也会进行控制反转。
指定属性参数值
可以使用 WithPropertyValue 指定实例中属性的值。
kernel.Bind<IDiscountHelper>().To<DefuaultDicountHelper>().WithPropertyValue("DiscountSize", 50M)
会传递50M到DefuaultDicountHelper里面的 DiscountSize属性。
指定构造器参数
可以使用 WinthConstructorArugment方法指定构造器中参数的值。
kernel.Bind<IDiscountHelper>().To<DefuaultDicountHelper>().WithConstructorArgument("discountParam",50M); public DefuaultDicountHelper(decimal discountParam)
{
DiscountSize = discountParam;
}
条件绑定
可以针对依赖注入设置对应条件,例如:要创建 LinqValueCalculator对象时,使用FlexibleDiscountHelper 作为 IDiscountHelper接口的实现。
kernel.Bind<IDiscountHelper>().To<FlexibleDiscountHelper>().WhenInjectedInto<LinqValueCalculator>();
WhenInjectedInto<T>() 当要被注入的类是类型T时,进行绑定
WhenClassHas<T>() 当被注入的类以注解属性进行注释,而类型为T时,进行绑定
作用域
可以设置绑定的作用域
kernel.Bind<IValueCalculator>().To<LinqValueCalculator>().InRequestScope();
InRequestScope() 创建一个单一实例,用于解析一个HTTP请求中各个对象的依赖项
InThreadScope() 创建一个单一实例,将其用于解析一个线程中各个对象的依赖项
InSingletonScope() 使其共享于整个应用程序