这三个工具,应该是每个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. Android PickerView滚动选择器的使用方法

    手机里设置闹钟需要选择时间,那个选择时间的控件就是滚动选择器,前几天用手机刷了MIUI,发现自带的那个时间选择器效果挺好看的,于是就自己仿写了一个,权当练手.先来看效果: 效果还行吧?实现思路就是自定 ...

  2. Xib文件的使用

  3. 浅谈C# 匿名变量

    每次写博客,第一句话都是这样的:程序员很苦逼,除了会写程序,还得会写博客!当然,希望将来的一天,某位老板看到此博客,给你的程序员职工加点薪资吧!因为程序员的世界除了苦逼就是沉默.我眼中的程序员大多都不 ...

  4. ASP.NET页面传值之Server.Transfer 和Response.Direct

    先看实例: B.apsx:         public string TextBox1Text         {             get             {             ...

  5. Effective C++ 2.构造 析构 赋值运算

    //条款07:为多态基类声明virtual析构函数 // 1.若基类的析构函数不定义为虚函数,由于基类的指针或引用可以指向派生类的对象,则在删除基类对象的时候可能会出错,导致破坏数据结构. // 2. ...

  6. PostgreSQL应用相关问题解决

    PostgreSQL中是否区分聚簇索引与非聚簇索引的问题? 答:PostgreSQL中区分聚簇索引与非聚簇索引. 示例如下: 创建聚族索引: CREATE INDEX test_ind ON yy ( ...

  7. max texture size of ios device

  8. eclipse不自动弹出提示

    最近公司电脑上的Eclipse没有了自动提示功能,也不是全部不提示,大多数情况下按下“alt+/”键还会产生提示,但是当我在java项目中邪main方法和syso的时候,“alt+/”则会失效,今天在 ...

  9. 工龄居然这么有用![Reprint]

    工龄有多重要?你恐怕未必知道,别以为没啥大不了,事实上,工龄会从各方面影响你的生活 .为了自己的权益,关于工龄的这些事儿,你必须要了解! 1.影响带薪年休假 (1)职工本单位累计工作满1年不满10年的 ...

  10. [原创]java WEB学习笔记70:Struts2 学习之路-- 输入验证,声明式验证,声明是验证原理

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...