这三个工具,应该是每个MVC程序员的兵工厂中的一部分。DI容器,单元测试框架,mocking 工具。Ninject是我们偏爱的DI容器,它简单,高雅,并且容易使用。这里有很多复杂的替代品,但是我们喜欢Ninject最小配置的工作方式。如果你不喜欢Ninject,可以使用Unity,它是微软提供的替代品。

单元测试方面,我们使用VS2010内置的 NUnit,它是.Net 单元测试框架中最受欢迎的一个。

Mocking 工具套装,我们选择 Moq。如果你不喜欢它,可以使用Rhino Mocks这个不错的替代品。

1 使用 Ninject

在原书中第四章,The MVC Pattern 中,我们介绍过DI的思想,用来在我们的MVC程序中的组件解耦。为了做到这点,我们需要结合接口和DI。

}

IValueCalculator 接口中定义了一个方法,它接受一个或多个Product对象,并返回累积的值。我们将接口部署在 LinqValueCalculator类上,它使用Linq延期方法Sum,灵巧地生成Product对象们的Price属性合计。然后,我们需要创建一个会使用到IVaueCalculator的类,即ShoppingCart,这个类是为DI设计的。Shoppingcart类的构造器需要一个实现了IValueCalculator接口的类,作为参数,为DI做准备。CalculateStockValue方法创建一个Product对象数组,然后调用IValueCalculator接口中的ValueProducts,来得到合计。

我们成功地将ShoppingCart类和LinqValueCalculator类解耦,这两个类都依赖IValueCalculator,但是ShppingCart与LinqValueCalculator没有直接关系。事实上,它甚至不知道LinqValueCalculator的存在。我们能改变LinqValueCalculator的实现,甚至用一个新的IValuecalculator的实现完全替代它。

Product类与这三个类有直接关系,我们不用担心这点。Product 是一个 domain model 类型的等价物,我们期望这样的类,强耦合,依赖我们的程序。如果我们不构建MVC程序,我们也许持不同的观点,并解耦Product。

我们的目标是能够创建一个ShoppingCart的实例,并注入一个IValueCalculator类的实现,作为构造函数的参数。这是我们偏爱的DI容器Ninject所扮演的角色。但是在我们展示Ninject之前,我们需要设置VS。

1.1 使用Ninject开始

要开始使用Ninject,我们需要创建一个Ninject kernel的实例,这个对象,我们会用来与Ninject交流。

IKernel ninjectKernel =new StandardKernel();

一旦创建kernel,Ninject会完成两个阶段的工作。第一是绑定你想要使用你已经创建的接口关联的类型。在这种情况下,我们想要告诉Ninject,当它收到一个请求,请求IValueCalculator的实例时,它应该创建并返回一个LinqValueCalculator类的实例。我们用定义在IKernel接口中的Bind和To方法做这样的事情。

ninjectKernel.Bind<IValueCalculator>().To<LinqValueCalculator<();

这段声明将IValueCalculator接口绑定到LinqValueCalculator实例类上。我们指定我们想要注册的接口,将它作为Bind方法的一般类型参数,并传递我们想要的具体实例的类型,作为第二个参数。

第二阶段,是使用Ninject的Get方法,创建一个实施接口的对象,并将它传递给ShoppingCart类的构造器。

Console.WriteLine("Total:{0:c}", cart.TotalPrice());

我们指定我们想要实例化的接口,作为Get方法的一般类型参数。Ninject浏览我们定义的绑定,看到我们将IValueCalculator绑定到LinqValueCalculator,然后为我们创建一个新的实例。我们然后将实例注入到ShoppingCart类的构造器,并调用TotalPrice方法,它会反过来调用接口中定义的方法。

ShoppingCart cart =new ShoppingCart(new LinqValueCalculator());

可以简化为这样。

1.2 创建依赖链

当我们请求Ninject创建一个类型,它会检查类型之间的耦合。如果有附加选项,Ninject解决他们,并创建所有必须的类的实例。

}

IDiscounHelper定义了一个ApplyDiscount方法,它会应用一个decima值折扣。DefaultDiscounterHelper类实现这个接口。我们可以将IDiscountHelper借口添加为LinqValueCalculator的依赖。

}

最新添加的构造器,需要传递一个IDiscountHelper接口的实现,它被用在ValueProducts方法,在处理累积Product对象的值时,应用打折。我们使用Ninject kernel将IDiscountHelper接口绑定到类的实现上。

ShoppingCart cart =new ShoppingCart(calImpl);

我们不用不用改变任何代码来创建IValueCalculator的实现。当需要IValueCalculator时,Ninject知道我们想要LinqValueCalculator类被实例化。他已经检验过这个类,并发现它基于一个接口实现。Ninject创建一个DefaultDiscountHelper的实例,将它注入到LinqValueCalculator类的构造器,并将结果作为IValueCalculator返回。Ninject检查所有用这种方式实例化依赖的类,无论它的依赖链有多长或多复杂。

1.3 指定属性和参数的值

我们能配置Ninject创建的类,来提供当我们将接口绑定到它的实现上时的属性细节。我们修正了StandardDiscountHelper类,使它暴漏一个方便的属性,来指定折扣的程度。

}

当我们使用Ninject将具体的类绑定到类型,我们可以使用WithPropertyValue方法,设置DefaultDiscountHelper类中DiscountSize属性的值。

ninjectKernel.Bind<IDiscountHelper>().To<DefaultDiscountHelper>().WithPropertyValue("DiscountSize",50M);

我们必须以字符串的形式提供属性的名字。我们不用改变任何其他的绑定,也不用改变Get方法的使用方式。属性的值,会随着DefaultDiscountHelper构建时设置。

如果你有多个值需要设置,可以链式调用WithPropertyValue方法。

也可以给构造函数传递参数

ninjectKernel.Bind<IDiscountHelper>().To<DefaultDiscountHelper>().WithConstructorArgument("discountParam", 50M);

1.4 使用自绑定

自绑定,是将Ninject完全整合进你代码的一个有用的特性,具体的类能从Ninject kernel请求。这看起来像是在做一件无聊的事情,但意味着我们不需要像以下代码那样,手工执行初始化DI。

ShoppingCart cart =new ShoppingCart(calcImpl);

而是可以简单地请求一个ShoppingCart实例,让Ninject挑选出依赖于IValueCalculator类。

ShoppingCart cart = ninjectKernel.Get<ShoppingCart>();

如果我们花时间注册一个自绑定类型,我们能在接口上使用这些特性,像为构造器参数和属性指定值。要注册自绑定,偶们使用ToSelf方法

ninjectKernel.Bind<ShoppingCart>().ToSelf().WithParameter("<parameterName>", <paramvalue>);

ShoppingCart绑定自身,调用WithParameter方法,为虚构的属性提供值。你可以仅在具体的类上使用自绑定。

1.5 绑定到派生类型

尽管我们关注接口,我们也使用Ninject绑定具体的类。我们既能绑定具体的类自己,也能绑定到一个派生类型。

}

我们能绑定父类,这样当我们从Ninject请求一个它的实例时,派生类的一个实例会被创建。这个技术用来绑定抽象类到它的具体实现时,工作的非常好。

1.6 使用条件绑定

使用Ninject,我们能绑定同一个接口的多个实现,或者同一个类的多个派生,使用指令,告诉它在不同的情况下应该使用哪个。下面我们创建一个IValueCalculator接口的新的实现:

ninjectKernel.Bind<IValueCalculator>().To<IterativeValueCalculator>().WhenInjectedInto<LimitShoppingCart>();

我们对IValueCalculator有一个原始的绑定,Ninject试图找到最匹配的绑定,如果条件不满足,它会使用默认绑定,到相同的类和接口。所以Ninject有一个退回的值。最有用的条件绑定方法:

Method Effect
When(predicate) 当条件中的Lambda表达式等于true时
WhenClassHas<T>() 当类注入含有一个指定类型的属性
WhenInjectedInto<T>() 当类被注入到类型T

1.7 在mvc中使用Ninject

首先要创建一个派生自System.Web.Mvc.DefaultControllerFactory的类。DefaultControllerFactory类是MVc用来默认创建controller 类的使用。

这类创建了一个Ninject kernel,并使用它来为通过GetControllerInstance方法创建的,当它想要的一个controller对象时,被MVC框架调用的controller类,的请求服务。我们不需要使用Ninject明确地绑定controller类。我们依靠默认的自绑定特性,自从controller成为System.Web.Mvc.Controller派生的一个具体类。

AddBindings方法,允许我们为想要保持低耦合的套件和其他组件添加其他的Ninject绑定。我们也能使用这个方法,做诶一个绑定controller类的时机——需要附加构造器参数或属性值。

一旦我们创建了这个类,我们必须使用MVC框架注册它。

现在,MVC框架会使用我们的NinjectControllerFactory来获得controller类的实例,Ninject会自动处理DI到controller。

【Pro ASP.NET MVC 3 Framework】.学习笔记.2.MVC的主要工具-Ninject的更多相关文章

  1. Pro ASP.NET MVC 5 Framework.学习笔记.6.3.MVC的必备工具

    每个MVC程序员的军火库中,都有这三个工具:一个依赖注入(DI)容器,一个单元测试框架,一个模拟工具. 1.准备一个示例项目 创建一个ASP.NET MVC Web Application的Empty ...

  2. Pro ASP.NET MVC 5 Framework.学习笔记.6.4.MVC的必备工具

    2.5.创建链式依赖 当你请求Ninject创建一个类型,它检查该类型的依赖是否声明.它也会检查该依赖是否依赖其他类型.如果这里有附加依赖,Ninject自动解决他们,并创建请求的所有类的实例.正是由 ...

  3. 【ASP.NET MVC 学习笔记】- 05 依赖注入工具Ninject

    本文参考:http://www.cnblogs.com/willick/p/3223042.html 1.Ninject是一款轻量级的DI工具,可通过VS的插件NuGet将其引用到项目中. 2.使用N ...

  4. ASP.NET MVC Web API 学习笔记---第一个Web API程序

    http://www.cnblogs.com/qingyuan/archive/2012/10/12/2720824.html GetListAll /api/Contact GetListBySex ...

  5. ASP.NET Core Web开发学习笔记-1介绍篇

    ASP.NET Core Web开发学习笔记-1介绍篇 给大家说声报歉,从2012年个人情感破裂的那一天,本人的51CTO,CnBlogs,Csdn,QQ,Weboo就再也没有更新过.踏实的生活(曾辞 ...

  6. 一起学ASP.NET Core 2.0学习笔记(二): ef core2.0 及mysql provider 、Fluent API相关配置及迁移

    不得不说微软的技术迭代还是很快的,上了微软的船就得跟着她走下去,前文一起学ASP.NET Core 2.0学习笔记(一): CentOS下 .net core2 sdk nginx.superviso ...

  7. MVC缓存OutPutCache学习笔记 (二) 缓存及时化VaryByCustom

    <MVC缓存OutPutCache学习笔记 (一) 参数配置> 本篇来介绍如何使用 VaryByCustom参数来实现缓存的及时化.. 根据数据改变来及时使客户端缓存过期并更新.. 首先更 ...

  8. MVC缓存OutPutCache学习笔记 (一) 参数配置

    OutPutCache 参数详解 Duration : 缓存时间,以秒为单位,这个除非你的Location=None,可以不添加此属性,其余时候都是必须的. Location : 缓存放置的位置; 该 ...

  9. Entity Framework 学习笔记(2)

    上期回顾:Entity Framework 学习笔记(1) Entity Framework最主要的东西,就是自己创建的.继承于DbContext的类: /// <summary> /// ...

  10. Entity Framework学习笔记

    原文地址:http://www.cnblogs.com/frankofgdc/p/3600090.html Entity Framework学习笔记——错误汇总   之前的小项目做完了,到了总结经验和 ...

随机推荐

  1. Flume-ng+Kafka+storm的学习笔记

    Flume-ng Flume是一个分布式.可靠.和高可用的海量日志采集.聚合和传输的系统. Flume的文档可以看http://flume.apache.org/FlumeUserGuide.html ...

  2. Android解决java.lang.OutOfMemoryError: bitmap size exceeds VM budget(转)

    昨天遇到这个问题就是从一个输入流里调用BitmapFactory.decodeStream(this.getContentResolver().openInputStream(uri))得到一个bit ...

  3. Centos php项目发布问题

    LAMP环境,项目运行错误日志路径:/var/log/httpd 错误日志例如: [Sat Jul :: ] [error] [client , referer: http://192.168.100 ...

  4. iOS面试必看,最全梳理

    序言 目前形势,参加到iOS队伍的人是越来越多,甚至已经到供过于求了.今年,找过工作人可能会更深刻地体会到今年的就业形势不容乐观,加之,培训机构一火车地向用人单位输送iOS开发人员,打破了生态圈的动态 ...

  5. SQL2008中Merge Into的用法

    在SQL2008中,新增了一个关键字:Merge,这个和Oracle的Merge的用法差不多,只是新增了一个delete方法而已.下面就是具体的使用说明: 首先是对merge的使用说明: merge ...

  6. Java基础之集合框架——使用堆栈Stack<>对象模拟发牌(TryDeal)

    控制台程序. public enum Rank { TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, JACK, QUEEN, KING, A ...

  7. (Command Pattern)命令模式

    定义 将“请求”封装成对象,以便使用不同的请求.队列或者日志来参数化其他对象.命令模式也支持可撤销的操作. 结构图: 命令模式的角色划分: Reciever(命令的接收者):接收命令,并知道如何进行必 ...

  8. wampserver环境下,安装ucenter1.6.0

    1,)从官网下载UCenter_1.6.0_SC_UTF8.zip,解压拷贝upload到www下,重命名upload->ucenter; 2,)D:\wamp\bin\apache\Apach ...

  9. Three.js基础探寻十——动画

    本篇将介绍如果使用Three.js进行动态画面的渲染.此外,将会介绍一个Three.js作者写的另外一个库stat.js,用来观测每秒帧数(FPS). 1.实现动画效果 1.1 动画原理 对于Thre ...

  10. The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation. 怎么解决

    cd 文件 pod install --no-repo-update 就可以了