MVC依赖性注入概述
MVC框架之所以如此受欢迎的原因之一就是它十分注意支持关注分离,使各个功能部件尽量能够相互独立。今天我们就来看看MVC4如何使用DI方法实现一些组件的独立,使本来结合紧密的部件,松耦合。我现在所说的对于.net的一些初学者来说可能有点拗口,其实我也是一个实打实的初学者,自己开始看这段话的时候迟迟不能理解,但是当看了实例之后,消化了一下就还算是懂得了其中的一些韵味了。下面就让我来和大家分享一下我自己所理解的依赖性注入。希望大家能多指教。
那么接下来我们来看一个简单的例子,用Demo说话
我们新建一个MVC4的项目吧

然后选择Basic模板

点击Ok创建好项目
接着在Models文件夹添加一个IEmailSender接口,代码如下
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace DIShow.Models
{
public interface IEmailSender
{
public string SendEmail();
}
}
接着再添加一个EmailSender类实现IEmailSender接口,代码如下
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web; namespace DIShow.Models
{
public class EmailSender:IEmailSender
{
public string SendEmail()
{
return "My Name is SendEmail,My Type is EmailSender";
}
}
}
现在我们在Controller文件夹里添加一个HomeController
我们要实现的功能就是在Controller里调用SendEmail方法来发送一个邮件。
我们在controller里添加如下代码就可以了。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using DIShow.Models; namespace DIShow.Controllers
{
public class HomeController : Controller
{
private IEmailSender emailSender;
public string Index()
{
emailSender = new EmailSender();
return emailSender.SendEmail();
} }
}
这个时候我们运行程序,就可以看到浏览器里的输出

现在我们唯一可以确定的就是这个程序时正确的。
那么现在我们就来谈谈这样简单的一个程序可以怎样做,来让他更为合理,具有清晰的结构。
首先我们可以看到,我们有一个接口和一个实现这个接口的类,肯定有同学会想问,就这样的程序干嘛还要多此一举搞个接口,直接在controller里面实例化这个类,再调用SendEmail方法就好了。我想说的是,接口只是为了后面的改进做一个铺垫,现在看来确实是可有可无。
然后现在我提出一个问题,要是我有多个发送邮件的程序,也就是说有多个类似于EmailSender这样的类。要是我想换一个发送程序,岂不是我每次必须要修改控制器中的代码,以此来切换发送程序。这样的做法对于很小的程序来说还好,对于稍微大一点的程序就会变得很不合理。这样就把控制器的代码变得十分繁琐了。而且对于MVC程序来说控制器就相当于大脑,你不能总是修改大脑,最合理的方式就是修改提供程序,然后大脑只需要一个调用执行该方法的接口就行了,并不需要关心具体是怎么实现的。回到我们现在的例子,我们要实现的效果就是在controller里面不出现EmailSender,只需要一个IEmailSender接口。我们只需要实例化这个接口的具体实现就行了。所以我们可以对控制器中的代码进行如下改进
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using DIShow.Models; namespace DIShow.Controllers
{
public class HomeController : Controller
{
private IEmailSender emailSender;
public HomeController(IEmailSender emailSender)
{
this.emailSender = emailSender;
}
public string Index()
{
return emailSender.SendEmail();
} }
}
我们可以看到这时我们就实现了HomeController和EmailSender之间毫无联系,当然这样的程序时没办法运行的,因为程序并不知道如何实例化IEmailsender这个接口,虽然有一个实现了这个接口的类,但是我们并没有告诉程序应该用哪个类去实例化这个接口。所以接下来我们就要去告诉程序应该用哪个类去实例化这个接口。
解决问题的方法就是“DI容器”,这个容器就是在接口(例如IEmailSender)和实现接口的具体类(例如EmailSender)之间担任一个中间人,由他来处理具体通过实例化哪个类来实例化接口。
而DI容器应该如何实现呢,两种方法,第一种就是自己创建一个DI容器,第二种就是用网上的开源代码,本人用的是Ninject包,网址:http://www.ninject.org
而在本篇博客中,由于作者本人能力有限,所以将只演示第二种方法。
大家可以在我提供的网址上看一下该包的具体细节然后下载包来进行使用,也可以直接在VS中的引用中进行安装。如下图


安装好后接下来我们就开始用使用这个包来帮助我们创建DI容器
第一步:创建一个依赖性链解析器
这个解析器就是类似搞出一个中介,让程序知道哪一个类去实例化哪一个接口。我们可以在mvc项目中,新建一个文件夹,例如Infrastructure,然后在里面建一个类:NinjectDependencyResolver 并实现IDependencyResolver接口,代码如下
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Ninject;
using System.Web.Mvc;
using DIShow.Models; namespace DIShow.Infrastructure
{
public class NinjectDependenceyResolver : IDependencyResolver
{
private IKernel kernel;
public NinjectDependenceyResolver()
{
kernel = new StandardKernel();
AddBindings();
}
public object GetService(Type serviceType)//IDependencyResolver的方法
{
return kernel.TryGet(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)//IDependencyResolver的方法
{
return kernel.GetAll(serviceType);
}
private void AddBindings()
{
kernel.Bind<IEmailSender>().To<EmailSender>();
}
}
}
第二步:注册依赖解析器
通过注册依赖解析器来告诉MVC框架,用户希望使用自己的依赖解析器,那么在哪里注册呢,当然是在管理整个程序运行的地方注册-Global.asax.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
using DIShow.Infrastructure; namespace DIShow
{
// Note: For instructions on enabling IIS6 or IIS7 classic mode,
// visit http://go.microsoft.com/?LinkId=9394801 public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas(); WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles); DependencyResolver.SetResolver(new NinjectDependenceyResolver());
}
}
}
DependencyResolver.SetResolver(new NinjectDependenceyResolver())便实现了注册
通过以上两步DI容器的创建和注册就已经搞定了。
现在我们的这个小项目的依赖性注入就完全搞定了,我们来运行程序检测一下正确与否

事实说明是正确的。
最后我们还是来简单总结一下吧。
首先我们来梳理一下程序的运行过程:程序启动,根据路由系统我们到了HomeController,然后运行到HomeController构造函数的时候发现需要传入一个IEmailSender的实例化对象。这个时候程序回到Global当中,发现Global确实注册这样一件事,就是我们指定了怎样去实例化接口。通过我们的注册信息,我们找到了我们的DI容器,也就是NinjectDependenceyResolver类。然后我们在这个类里面传入一个类型给GetService,然后它通过查看我们的绑定信息,这个中介就发现我们是把IEmailSender绑定到EmailSender上面去的。于是就 实例化了EmailSender得到了一个对象,最后返回给了在HomeController中的构造函数中的参数sendEmail。于是后面就可以成功执行方法了。
然后我们来看一下实现这些过程主要做了那几步:
1.写出接口和实现类。
2.在控制器中只调用接口方法,不出现具体类
3.创建一个DI容器,将接口和具体类绑定
4.在Global中注册这个容器
就这样四步就搞定了。以后要是想要切换另一个发送程序,只需要在DI容器中将接口绑定到另一个实际类上就可以了,控制器不需要做任何修改。
好啦,我的分享就到此为止了,以后要是学到了更多有意思的东西还会和大家继续分享的。
MVC依赖性注入概述的更多相关文章
- .NET 用 Unity 依赖注入——概述注册和解析类型(1)
本文内容 Unity 概述 环境 一个真实的例子 类型注册(Type Registrations) 解析类型(Resolving Types) 跳槽,新公司使用了 Unity,初步看了一下,公司的使用 ...
- 解决Autofac MVC 自动注入在 Areas拆分到不同dll下的注入失败问题
由于项目业务复杂,创建了多个Areas 并把他们放在了不同的项目中,项目使用AutoFac做的IOC 配置代码为 public class MvcApplication : System.Web.Ht ...
- Asp.Net MVC 之 Autofac 初步使用2 集成mvc 属性注入以及自动注入
首先看下Demo2的结构 然后下面一步步将Autofac集成到mvc中. 首先,定义Model Product.cs public class Product { public int Id ...
- 基础教程:视图中的ASP.NET Core 2.0 MVC依赖注入
问题 如何在ASP.NET Core MVC Views中注入和使用服务. 解 更新 启动 类来为MVC添加服务和中间件. 添加一项服务 添加一个Controller,返回 ViewResult. 添 ...
- MVC架构模式概述
MVC MVC概述: Model–view–controller (MVC) is a software architectural pattern for implementing user int ...
- MVC 依赖注入
本人主要是写给我自己看的,文章没有过多的解释,只留下步骤. 目的:面向接口编程,做到低耦合,高内聚 1.利用Nuget 管理工具,安装Ninject. 2.随便新建一个接口和一个实现类,我在此项目中是 ...
- MVC 依赖注入扩展
需求: 小明想要完成一个功能F,需要一把锤子T. 有两种办法可以实现: 1)小明很爱动手,精力很旺盛,于是,自己创建一个具有功能F的锤子T,并使用T来完成F: 2)小明很懒,天天睡大觉,于是,他叫小健 ...
- spring mvc处理流程概述
大部分Java应用都是Web应用,展现层是Web应用不可忽略的重要环节.Spring为展现层提供了一个优秀的Web框架-Spring MVC.和众多其他Web框架一样,它基于MVC设计理念,此外,它采 ...
- 1..net mvc的原理概述
请求过来,根据ip和端口,由iis服务器进行接收,如果是静态文件则直接返回文件内容,如果无法解析,则根据映射规则找到对应请求后缀 的ASPNET_ISAPI.dll处理程序集,交由其进行处理. 1.此 ...
随机推荐
- Hadoop学习笔记—15.HBase框架学习(基础知识篇)
HBase是Apache Hadoop的数据库,能够对大型数据提供随机.实时的读写访问.HBase的目标是存储并处理大型的数据.HBase是一个开源的,分布式的,多版本的,面向列的存储模型,它存储的是 ...
- 企业IT管理员IE11升级指南【7】—— Win7和Win8.1上的IE11功能对比
企业IT管理员IE11升级指南 系列: [1]—— Internet Explorer 11增强保护模式 (EPM) 介绍 [2]—— Internet Explorer 11 对Adobe Flas ...
- ASP.NET MVC学前篇之请求流程
ASP.NET MVC学前篇之请求流程 请求流程描述 对于请求的流程,文章的重点是讲HttpApplication和HttpModule之间的关系,以及一个简单的示例实现.(HttpModule又是M ...
- [ASP.NET Web API]如何Host定义在独立程序集中的Controller
通过<ASP.NET Web API的Controller是如何被创建的?>的介绍我们知道默认ASP.NET Web API在Self Host寄宿模式下用于解析程序集的Assemblie ...
- WCF wsHttpBinding之Transport security Mode, clientCredentialType=”Basic”
原创地址:http://www.cnblogs.com/jfzhu/p/4071342.html 转载请注明出处 如何在WCF中使用Transport Security Mode,以及如何创建证书,请 ...
- TODO:Linux安装PHP MongoDB驱动
TODO:Linux安装PHP MongoDB驱动 PHP利于学习,使用广泛,主要适用于Web开发领域. MongoDB的主要目标是在键/值存储方式(提供了高性能和高度伸缩性)以及传统的RDBMS系统 ...
- sql复习第五次
1.在数据库范围内,关系的每一个属性值是不可分解的 关系中不允许出现重复元组 由于关系是一个集合,因此不考虑元组的顺序 2.笛卡儿积是两个关系的所有元组组合而成的,而等值联接是由笛卡儿积和选择运算组合 ...
- LINQ系列:Linq to Object生成操作符
生成操作符从现有序列值中创建新的序列. 1. Empty Empty操作符返回一个指定类型的空集. 1>. 原型定义 public static IEnumerable<TResult& ...
- HighCharts从数据库中读取数据
1.index.js router.get('/', function(req, res, next) { res.render('index', { title: 'Express' }); }); ...
- javascript面向对象系列第二篇——创建对象的5种模式
× 目录 [1]字面量 [2]工厂模式 [3]构造函数[4]原型模式[5]组合模式 前面的话 如何创建对象,或者说如何更优雅的创建对象,一直是一个津津乐道的话题.本文将从最简单的创建对象的方式入手,逐 ...