说到依赖注入 ,首先要提到控制反转,控制反转(Inversion of Control,英文缩写为IoC)是一个重要的面向对象编程的原则,目的是来削减计算机程序的耦合问题控制反转一般分为两种类型,
依赖注入(Dependency Injection,简称DI)和依赖查找。两者的区别在于,前者是被动的接收对象,在类A的实例创建过程中即创建了依赖的B对象,通过类型或名称来判断将不同的对象注入到不同的
属性中,而后者是主动索取响应名称的对象,获得依赖对象的时间也可以在代码中自由控制。但是依赖注入的应用比较广泛。MVC的一个重要特征是关注点分离(separation of concerns)。应用程序的
各部分组件应该尽可能多的相互独立、尽可能少的相互依赖,关于依赖注入详细介绍的文章园子里已经很多了,如T2噬菌体的依赖注入那些事儿
依赖注入有如下实现方式:基于接口。实现特定接口以供外部容器注入所依赖类型的对象。基于 set 方法。实现特定属性的public set方法,来让外部容器调用传入所依赖类型的对象。基于构造函数。实现特定参数的构造函数,在新建对象时传入所依赖类型的对象。
NET平台中有许多优秀的IOC框架如:Ninject,Spring.NET,ObjectBuilder,Structuremap,CastleProject,Seasar等。
目前我在学习MVC阶段,只接触了Ninject,以下的代码也是基于这个框架编写的。
首先使用VS2012的NuGet下载安装Ninject
在项目中添加 NinjectControllerFactory类如下:
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:后面再来添加绑定 } }
使用repository模式将领域模型从客户代码和数据映射层之间解耦出来。
创建一个通用的存储接口IRepository
public interface IRepository<T> where T : class { IQueryable<T> Lists { get;} }
创建模型类
public class Book { public int ID { get; set; } public string Title { get; set; } public string Isbn { get; set; } public string Summary { get; set; } public string Author { get; set; } public byte[] Thumbnail { get; set; } public decimal Price { get; set; } public DateTime Published { get; set; } }
创建实现IRepository<T>接口的 BookRepository
public class BookRepository : IRepository<Book> { public IQueryable<Book> Lists { get { return GetBooks().AsQueryable(); } } private static List<Book> GetBooks() { //为了演示,这里手工造一些数据,后面会介绍使用EF从数据库中读取。 List<Book> books = new List<Book>{ new Book { ID = 1, Title = "ASP.NET MVC 4 编程", Price = 52}, new Book { ID = 2, Title = "CLR Via C#", Price = 46}, new Book { ID = 3, Title = "平凡的世界", Price = 37} }; return books; } }
接下来修改前面NinjectControllerFactory类的 AddBindings()方法
private void AddBindings() { // todo:后面再来添加绑定 ninjectKernel.Bind<IRepository<Book>>().To<BookRepository>(); }
这样Ninject会自动帮我们创建我们所需要的类的实例
我们需要在Global.asax文件中注册NinjectControllerFactory类
protected void Application_Start() { . . . . ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory());//注册NinjectControllerFactory类 }
创建BookController控制器
public class BookController : Controller { // // GET: /Book/ private IRepository<Book> bookrepository; public BookController(IRepository<Book> bookRepository, IRepository<Author> authorepository) { this.bookrepository = bookRepository; this.authorepository = authorepository; } public ActionResult Index() { return View(); } public ViewResult BookList() { return View(bookrepository.Lists); } }
创建BookList视图页面代码如下
@model IQueryable<BookShopDomain.Book> @{ ViewBag.Title = "BookList"; } @Html.Action("View1") <h2>BookList</h2> @foreach (var book in Model) { <div class="item" style="border-bottom: 1px dashed silver;"> <h3>@book.Title</h3> <p>价格:@book.Price.ToString("c") </p> </div> }
打开浏览器,在地址栏输入一面地址程序运行成功:
一个简单的mvc依赖注入程序就完成了。这里我只是简单的使用Ninject,还需继续深入学习。