MVC Ninject 框架
吐个槽!
今天看博客的时候看到一段话,借用一下“首先我不喜欢大量的配置文件进行配置,那简直是噩梦,比学习一门编程语言还痛苦”
哥们多少次学习JAVA就是让这一堆配置文件弄的一点脾气都没。
Ninject就不需要用配置文件进行配置。只通过代码就好了,完全符合面向对象思想,但是!!正因为缺少了配置文件,所以不能采用热插拔!残念!不过有舍有得。。具体项目具体斟酌吧
依赖注入的的好处(坏处)就不用唠唠叨叨的一直说了。
简单说一点吧:当今的软件开发为了解耦可以说是不择手段,依赖注入是个好手段。
什么是依赖注入
在一个类内部,不通过创建对象的实例而能够获得某个实现了公开接口的对象的引用。这种“需要”,就称为DI(依赖注入,Dependency Injection),和所谓的IoC(控制反转,Inversion of Control )是一个意思
DI模式可分为两个部分:一个是移除对组件的依赖,一个是通过构造函数来传递实现了公共接口的组件的引用(也可以通过set,其实是一个意思)
下面代码是典型的构造注入
public class ShoppingCart { IValueCalculator calculator; //构造函数,参数为实现了IValueCalculator接口的类的实例 public ShoppingCart(IValueCalculator calcParam) { calculator = calcParam; } //计算购物车内商品总价钱 public decimal CalculateStockValue() { Product[] products = { new Product {Name = "西瓜", Category = "水果", Price = 2.3M}, new Product {Name = "苹果", Category = "水果", Price = 4.9M}, new Product {Name = "空心菜", Category = "蔬菜", Price = 2.2M}, new Product {Name = "地瓜", Category = "蔬菜", Price = 1.9M} }; //计算商品总价钱 decimal totalValue = calculator.ValueProducts(products); return totalValue; } }
使用Ninject的步骤
1.创建Ninject核心对象:
IKernel ninjectKernel = new StandardKernel();
2.将实现了接口的类和接口绑定到一起:
//Bind里面是接口,To里面是实现接口的类 ninjectKernel.Bind<IValueCalculator>().To<LinqValueCalculator>();
3.通过Ninject核心对象获取我们要用的实现类(有两种获取方式):
//规规矩矩的写法(Get<>方法为静态方法)
IValueCalculator calcImpl = ninjectKernel.Get<IValueCalculator>();
//不规矩的写法,如果这样写的话就不需要第4步了。其实这样写符合面向对象思想,我们不需要关系ShoppingCart依赖了哪些接口,这也正是依赖注入的核心思想。
ShoppingCart cart = ninjectKernel.Get<ShoppingCart>();
这里的calcImpl虽然是接口类型,但实际上已经是实现了接口的子类(LinqValueCalculator类,面向对象思想,子类可以指向父类)
4.通过构造函数将calcImpl传递给其引用类。
ShoppingCart cart = new ShoppingCart(calcImpl);
一个最简单依赖注入已经完成了。(真的不是我吐槽JAVA中Spring MVC,我这些东西只用了4行代码就完成了一个依赖注入而且so easy,如果是SpringMVC 我就只能呵呵了。)
Ninject的一个牛逼的地方:
当我们请求Ninject创建某个类型的实例时,它会检查这个类型和其它类型之间的耦合关系。如果存在依赖关系,那么Ninject会根据依赖处理理它们,并创建所有所需类的实例。
什么意思呢?假如说我刚才的类LinqValueCalculator也引用了其他的接口,代码结构和ShoppingCart 类似,也是通过构造函数来传递所依赖的类。那我们是否也需要显示的写出和第4行代码类似的代码呢?
答案当然是否定的。不然怎么叫牛逼呢?那我需要干什么?我们只需要将LinqValueCalculator所依赖的接口和这个接口的实现类绑定一下就可以了ninjectKernel.Bind<>().To<>();
不管我们的嵌套层次有多深。Ninject都可以帮我们完成这些操作。
说到这我就有一个疑问。我一个接口可是被多个类实现的。你这样只能绑定一个类啊,而且如果我的实现类在被实例化时是需要给属性赋值的,也有可能构造函数里也是有参数的!放心你想到的大神们都想到了。接着往下看
如果是给属性赋值的话:ninjectKernel.Bind<IValueCalculator>().To<LinqValueCalculator>().WithPropertyValue("属性名",属性值);要给多个属性赋值,则可以在Bind和To方式后添加多WithPropertyValue,属性值是Object类型
如果是给构造函数赋值,只需要更改一行代码,将WithPropertyValue换成WithConstructorArgument,其他代码原来怎么写还是怎么写。如果构造函数有多个参数,则需在Bind和To方法后面加上多个WithConstructorArgument即可。
今天就学习到这。瞌睡了。。再看下去也记不住了
Ninject多种绑定方式
1.一般绑定。就上面介绍的那种。
2.派生类绑定(与接口绑定一样)
3.条件绑定
当一个接口有多个实现或一个类有多个子类的时候,我们可以通过条件绑定来指定使用哪一个实现或子类。通过WhenInjectedInto<>这个方法来指定条件
//这段代码的意思是当调用类为LimitShoppingCart时,则注入向接口IValueCalculater注入IterativeValueCalculatgor ninjectKernel.Bind<IValueCalculater>().To<IterativeValueCalculatgor>().WhenInjectedInto<LimitShoppingCart>();
在Web项目中使用Ninject
1.首先你得有个Web MVC项目。(这是废话)
2.在项目下,新建一个class,该类继承自DefaultControllerFactory
public class NinjectControllerFactory : DefaultControllerFactory { private IKernel ninjectKernel; public NinjectControllerFactory() { ninjectKernel = new StandardKernel(); AddBindings(); } protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType) { return controllerType == null ? null : (IController)ninjectKernel.Get(controllerType); } private void AddBindings() { // todo:后面再来添加绑定 } }
3.需在Global.asax文件的Application_Start方法中添加下面代码
protected void Application_Start() { ...... //设置Controller工厂(意思就告诉MVC框架:“哥您提供的Controller工厂类不行了,已经痿了,得用我自己的了”) ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory()); }
浙公网安备 33010602011771号