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.此 ...
随机推荐
- Linux环境下部署完JDK后运行一个简单的Java程序
前言 前一篇文章详细讲解了如何在Windows环境下安装虚拟机+Linux系统,并且成功部署了JDK. 不过部署完JDK之后,我们判断部署是否成功的依据是看"java -version&qu ...
- [.net 面向对象程序设计进阶] (11) 序列化(Serialization)(三) 通过接口 IXmlSerializable 实现XML序列化 及 通用XML类
[.net 面向对象程序设计进阶] (11) 序列化(Serialization)(三) 通过接口 IXmlSerializable 实现XML序列化 及 通用XML类 本节导读:本节主要介绍通过序列 ...
- 大叔也学Xamarin系列
回到占占推荐博客索引 我就是我,请叫我仓储大叔 大叔听很多客户说,xamarin的资料网上太少了,是的,大叔也相信,因为大叔在学xamarin里确实很费劲,只能看看androd for java了,呵 ...
- Hello World of OpenCascade
Hello World of OpenCascade eryar@163.com 摘要Abstract:以一个经典的Hello World程序为例开始对开源几何造型内核OpenCascade的学习. ...
- 理解DOM事件流的三个阶段
本文主要解决两个问题: 1.什么是事件流 2.DOM事件流的三个阶段 事件流之事件冒泡与事件捕获 在浏览器发展的过程中,开发团队遇到了一个问题.那就是页面中的哪一部分拥有特定的事件? 可以想象画在一张 ...
- 深入学习jQuery选择器系列第六篇——过滤选择器之状态选择器
× 目录 [1]焦点状态 [2]哈希状态 [3]动画状态[4]显隐状态 前面的话 过滤选择器的内容非常多,本文介绍过滤选择器的最后一部分——状态选择器 焦点状态 :focus :focus选择器选择当 ...
- Android音频开发之AudioRecord录音实现
前言: 其实在Android中录音可以用MediaRecord录音,操作比较简单.但是不能对音频进行处理.考虑到项目中做的是实时语音只能选择AudioRecord进行录音. 本文算是对AudioRec ...
- .cn根服务器被攻击之后
如果是互联网行业的人员应该知道,8月25日凌晨,大批的“.cn”域名的网站都无法访问,当然包括weibo.cn等大型网站.个人比较奇怪的一件事情是,微博PC网页版是:www.weibo.com,而mo ...
- IOS开发之自定义Button(集成三种回调模式)
前面在做东西的时候都用到了storyboard,在今天的代码中就纯手写代码自己用封装个Button.这个Button继承于UIView类,在封装的时候用上啦OC中的三种回调模式:目标动作回调,委托回调 ...
- 开发中 常用 js 记录(一)
(1)获得URL参数 function GetQueryString("url参数名") { var reg = new RegExp("(^|&)&qu ...