Asp.net MVC 中使用 Ninject 实现依赖注入
松耦合、针对抽象编程、不针对实现编程是面向对象设计的原则。依赖注入就是,在一个类的内部,不通过创建对象的实例而能够获得实现了某个公开接口的对象引用。所谓的控制反转也是相同的意思。把依赖的创建转移到了使用这些依赖的类的外部,反转的是依赖的创建。控制反转可以是通过依赖注入和服务定位器模式来实现。依赖注入特别适用于复杂的依赖关系的程序中。
在Asp.net MVC程序中,经常使用仓储模式来分离控制器和数据访问层。有利于进行单元测试和测试驱动开发(TDD)。
实现依赖注入可以使控制器和使用的仓储层相互独立,使用控制器减少了对仓储层的依赖。依赖注入可以通过直接构造方法注入和属性注入、IOC容器注入三种方式。
在Asp.net MVc中,使用NInject 实现依赖注入的步骤如下
1、安装 Ninject
在VS中在程序包管理控制台中输入 Install-Package Ninject -Project ApplicationName。则NuGet或自动下载和安装、引用Ninject的程序集。也可以直接使用 vs 的 工具 的管理窗口操作抽完Nuget下载。
2、 可以有两种方式。
第一种:
1、:建立一个控制器工厂类,接管控制器对象的创建。在ASP.NET MVC中,一个客户端请求是在特定Controller的Action中进行处理的。 默认情况下,ASP.NET MVC使用内置的Controller工厂类 DefaultControllerFactory来创建某个请求对应的Controller实例。有时候默认的Controller工厂不能满足我们实际的需求,我们就需要对这种默认行为进行扩展,即创建一个继承自DefaultControllerFactory类的自定义Controller工厂类并重写其中的一些方法。
public class NinjectControllerFactory: DefaultControllerFactory
{
private IKernel ninjectKernel;
protected override IController GetControllerInstance(RequestContext request requestContext,Type controllerType)
{
return controllerType== null ?null :(IController)njinectKernel.Get(controllerType);
}
// 添加绑定。
private void AddBindings()
{
_kernel.Bind<IStudentRepository>().To<StudentRepository>();
}
}
上面代码中的 ninjectKernel.Get(controllerType) 可获取到一个Controller实例。在这里如果手动实例化Controller类是一个非常复杂的过程,我们不知道Controller类有没有带参数的构造函数,也不知道构造函数的参数是什么类型。而使用Ninject只需要使用上面的一个Get方法就可以,Ninject内部会自动处理所有的依赖关系,智能地创建我们需要的对象。
2、需在Global.asax文件的Application_Start方法中添加下面代码:
protected void Application_Start() {
......
//设置Controller工厂
ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory());
}
第二种方式:实现 System.Web.MVc 命名空间下的IDepenednctyResolver接口
完整的代码如下:
1、模型类:Student
public class Student
{
public int ID { get; set; }
public string LastName { get; set; }
public string FirstName { get; set; }
public DateTime EnrollmentDate { get; set; }
public string FullName
{
get { return FirstName + LastName; }
}
}
}
2、建立仓储接口 IStudentRepository类,和实现接口StudentRepository类
public interface IStudentRepository:IDisposable
{
IQueryable <Student> GetStudents(); //IQueryable<>和IEumrable<>都可以,但使用 IQueryable<>效率高一些,因为他是延迟查询,只会查出需要使用的数据。为什么用IQueryable而不用IEnumerable作为返回类型?答案是:使用IQueryable,EF会根据调用者的Linq表达式先生成相应的SQL查询语句,然后到数据库中执行查询,查询出来的数据即是用户想要的数据;而使用IEnumerable,Linq表达式的过滤、排序等操作都是在内存中发生的,即EF会先从数据库中把整个表的数据查询出来放在内存中,然后由调用者使用Linq语句进行过滤、排序等操作。
IQueryable虽然可以很智能地根据Linq表达式生成相应的SQL语句,但毕竟有一个分析Linq表达式的过程,相对来说性能比IEnumerable要差。那么我们什么时候用IEnumerable,什么时候用IQueryable呢?我想,对于少量的数据(比如从数据库中读取应用程序相关的系统信息)和不需要对数据进行过滤操作的情况,用IEnumerable比较适合;对于数据量较大需要对数据进行过滤(比如分页查询)的情况,则用IQueryable比较合适
Student GetStudentByID(int? studetnID);
void InsertStduent(Student student);
void DeleteStudent(int? studentID);
void UpdateStudent(Student student);
void Save();
}
//实现仓储接口。
public class StudentRepository:IStudentRepository,IDisposable
{
private SchoolContext context;
public StudentRepository(SchoolContext context)
{
this.context = context;
}
public IQueryable <Student> GetStudents()
{
return context.Students.ToList();
}
public Student GetStudentByID(int? studetnID)
{
return context.Students.Find(studetnID);
}
public void InsertStduent(Student student)
{
context.Students.Add(student);
}
public void DeleteStudent(int? studentID)
{
Student student = context.Students.Find(studentID);
context.Students.Remove(student);
}
public void UpdateStudent(Student student)
{
context.Entry(student).State = EntityState.Modified;
}
public void Save()
{
context.SaveChanges();
}
private bool disposed = false;
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
context.Dispose();
}
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
3、实现IDendenctyResolver接口的 NinjectDependencyResolver。
public class NinjectDependencyResolver:IDependencyResolver
{
private readonly IKernel _kernel; //创建Ninject内核实例
public NinjectDependencyResolver()
{
_kernel = new StandardKernel();
AddBindings();
}
private void AddBindings() //绑定接口到实现了该接口的类
{
_kernel.Bind<IStudentRepository>().To<StudentRepository>();
// _kernel.Bind<IStudentRepository>().To<StudentRepositoryInMemory>();
}
public object GetService(Type serviceType) //【实现IDendcyResolver 接口的两个方法
{
return _kernel.TryGet(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
return _kernel.GetAll(serviceType);
}
}
4、同样需要的 globe.asax 中注册依赖解析器
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
DependencyResolver.SetResolver(new NinjectDependencyResolver()); //注册依赖解析容器。
}
5、控制器
public class StudentController : Controller
{
private IStudentRepository studentRepository;
//如果你正使用Dependenty injection 或者DI,你不需要默认的构造方法,因为DI软件将始终保证正确的仓储对象被提供。
public StudentController(IStudentRepository studentRepository)
{
this.studentRepository = studentRepository;
}
// GET: Student
public ActionResult Index()
{
return View(studentRepository.GetStudents());
}
StudentController的构造函数接受了一个IStudentRepository参数,当StudentController被实例化的时候,Ninject就为其注入了StudentRepository的依赖。
6、修改由基架自动生成的控制器方法,控制器由直接访问 数据库上下文变成访问 仓储接口。
如
// GET: Student
public ActionResult Index()
{
return View(studentRepository.GetStudents());
} 另外:还可以使用 Kernel内核对象来获取 接口的实现,比如
Student student =ninjectKernel.Get<IStudentRepository>(); GET<>方法返回的是绑定的 StudentRepository对象。
Asp.net MVC 中使用 Ninject 实现依赖注入的更多相关文章
- ASP.NET MVC中使用Unity进行依赖注入的三种方式
在ASP.NET MVC中使用Unity进行依赖注入的三种方式 2013-12-15 21:07 by 小白哥哥, 146 阅读, 0 评论, 收藏, 编辑 在ASP.NET MVC4中,为了在解开C ...
- 在ASP.NET MVC中使用Unity进行依赖注入的三种方式
在ASP.NET MVC4中,为了在解开Controller和Model的耦合,我们通常需要在Controller激活系统中引入IoC,用于处理用户请求的 Controller,让Controller ...
- [ASP.NET MVC 小牛之路]04 - 依赖注入(DI)和Ninject
本人博客已转移至:http://www.exblr.com/liam 为什么需要依赖注入 在[ASP.NET MVC 小牛之路]系列的理解MVC模式文章中,我们提到MVC的一个重要特征是关注点分离( ...
- ASP.NET MVC中使用Ninject
ASP.NET MVC中使用Ninject 在[ASP.NET MVC 小牛之路]系列上一篇文章(依赖注入(DI)和Ninject)的末尾提到了在ASP.NET MVC中使用Ninject要做的两件事 ...
- ASP.NET Core 中的框架级依赖注入
https://tech.io/playgrounds/5040/framework-level-dependency-injection-with-asp-net-core 作者: Gunnar P ...
- 【ASP.NET MVC 学习笔记】- 04 依赖注入(DI)
本文参考:http://www.cnblogs.com/willick/p/3223042.html 1.在一个类内部,不通过创建对象的实例而能够获得某个实现了公开接口的对象的引用.这种"需 ...
- 【ASP.NET MVC 学习笔记】- 05 依赖注入工具Ninject
本文参考:http://www.cnblogs.com/willick/p/3223042.html 1.Ninject是一款轻量级的DI工具,可通过VS的插件NuGet将其引用到项目中. 2.使用N ...
- ASP.NET Web API和ASP.NET Web MVC中使用Ninject
ASP.NET Web API和ASP.NET Web MVC中使用Ninject 先附上源码下载地址 一.准备工作 1.新建一个名为MvcDemo的空解决方案 2.新建一个名为MvcDemo.Web ...
- 在ASP.NET Web API和ASP.NET Web MVC中使用Ninject
先附上源码下载地址 一.准备工作 1.新建一个名为MvcDemo的空解决方案 2.新建一个名为MvcDemo.WebUI的空MVC应用程序 3.使用NuGet安装Ninject库 二.在ASP.N ...
随机推荐
- 【原】理解javascript中的闭包(***********************************************)
阅读目录 什么是闭包? 闭包的特性 闭包的作用: 闭包的代码示例 注意事项 总结 闭包在javascript来说是比较重要的概念,平时工作中也是用的比较多的一项技术.下来对其进行一个小小的总结 回到顶 ...
- 一个球,初始高度100,每次落下回弹一半高度,求第n次落下球走的距离
def get_height(n): if n==1: eturn 150 return 100+sum([200*pow(0.5,i) for i in range(1,n)])+100*pow(0 ...
- react map 遍历
1.map方法 注:map 返回的是一个新数组 class App extends Component { // constructor(props) { // super(props); // th ...
- 一个TAB的jquery简单写法2
<style> .honver{ color:red;} </style><script src="jquery-1.9.0.min.js">& ...
- 【转载】究竟啥才是互联网架构“高可用”
一.什么是高可用 高可用HA(High Availability)是分布式系统架构设计中必须考虑的因素之一,它通常是指,通过设计减少系统不能提供服务的时间. 假设系统一直能够提供服务,我们说系统的可用 ...
- javascript之scrollTop
下面的演示中,外层元素的高度值是200px,内层元素的高度值是300px.很明显,“外层元素中的内容”高过了“外层元素”本身.当向下拖动滚动条时,有部分内容会隐没在“外层元素的上边界”之外,scrol ...
- C#WinForm窗体监听/拦截操作动作
C#中的事件也是通过封装系统消息来实现的,如果你在WndProc函数中不处理该消息 那么,它会被交给系统来处理该消息,系统便会通过代理来实现鼠标单击的处理函数,因此你可以通过 WndProc函数来拦截 ...
- SDOI2016R1(不是解题报告)
话说洗澡的时候想了一堆要说的,坐到电脑前反而不知所措了-- 序章 听学长说他们都是省选一周前才停的课.然而我们这届--自聪哥韩大他们在省选两周前悄悄跑路后(据说班主任非常支持),信息小组内部一呼百应, ...
- VC 无边框对话框的任务栏右键菜单
MFC ,基于对话框的程序,属性为:Border : none. 程序运行后,在任务栏里面点右键,不会弹出类似下面的菜单: 在对话框的OnInitDialog里面添加如下语句即可: ModifySty ...
- (Android 即时通讯) [悬赏],不管是谁发现一个漏洞奖励人民币1000元!
悬赏,不管是谁发现一个漏洞奖励人民币1000元! 3Q Android 手机版即时通讯系统正式推出,可与电脑版 地灵(http://im.yunxunmi.com) 即时通讯系统互通! 适用于:小米 ...