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 ...
随机推荐
- jmeter Plugins Manager插件管理
在 https://jmeter-plugins.org/downloads/all/ 下载插件,放到lib/ext Download plugins-manager.jar and put it i ...
- 【Linux学习笔记】栈与函数调用惯例
栈与函数调用惯例(又称调用约定)— 基础篇 记得一年半前参加百度的校招面试时,被问到函数调用惯例的问题.当时只是懂个大概,比如常见函数调用约定类型及对应的参数入栈顺序等.最近看书过程中,重新回顾了这些 ...
- hdoj-1856-More is better【并查集】
More is better Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 327680/102400 K (Java/Others) To ...
- uml精粹——10.状态机图
10.状态机图state machine diagram 状态机图是常见的描写叙述一个系统行为的技术. 在面向对象的方法中,为单个类绘制一个状态机图来展示单个对象的生命周期行为. 见图10.1 图 ...
- scrollReveal 使用
传统的layzload只能适用于图片懒加载,而我们现在需要的是全部元素的懒加载! 官网:https://scrollrevealjs.org/ gitHub:https://github.com/jl ...
- IOS开发——网络编程总汇
关于IOS的网络编程,大家都会想到C实现的底层BSD ,CFNetwork和NSURL之类的库,虽然如今非常多第三方库非常方便,可是作为一名开发人员,也须要了解底层代码. 以下的思维导图是关于眼下开发 ...
- C#语言 循环语句
//Console.Write("请输入关卡数:"); //int a = int.Parse(Console.ReadLine()); //int s = 0; //if (a ...
- java设计模式----复合模式
复合模式:复合模式结合两个或以上的模式,组成一个解决方案,解决一再发生的一般性问题 要点: 1.MVC是复合模式,结合了观察者模式.策略模式和组合模式 2.模型使用观察者模式,以便观察者更新,同时保持 ...
- Android Menu开源项目整合工程
本实例整合了关于Android Menu的优秀开源代码,方便有需要用到Menu开源项目的小伙伴使用. 一.整合的项目有: SlidingMenu:https://github.com/jfeinste ...
- BZOJ 2115: [Wc2011] Xor DFS + 线性基
2115: [Wc2011] Xor Time Limit: 10 Sec Memory Limit: 259 MB Description Input 第一行包含两个整数N和 M, 表示该无向图中 ...