松耦合、针对抽象编程、不针对实现编程是面向对象设计的原则。依赖注入就是,在一个类的内部,不通过创建对象的实例而能够获得实现了某个公开接口的对象引用。所谓的控制反转也是相同的意思。把依赖的创建转移到了使用这些依赖的类的外部,反转的是依赖的创建。控制反转可以是通过依赖注入和服务定位器模式来实现。依赖注入特别适用于复杂的依赖关系的程序中。

在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 实现依赖注入的更多相关文章

  1. ASP.NET MVC中使用Unity进行依赖注入的三种方式

    在ASP.NET MVC中使用Unity进行依赖注入的三种方式 2013-12-15 21:07 by 小白哥哥, 146 阅读, 0 评论, 收藏, 编辑 在ASP.NET MVC4中,为了在解开C ...

  2. 在ASP.NET MVC中使用Unity进行依赖注入的三种方式

    在ASP.NET MVC4中,为了在解开Controller和Model的耦合,我们通常需要在Controller激活系统中引入IoC,用于处理用户请求的 Controller,让Controller ...

  3. [ASP.NET MVC 小牛之路]04 - 依赖注入(DI)和Ninject

    本人博客已转移至:http://www.exblr.com/liam  为什么需要依赖注入 在[ASP.NET MVC 小牛之路]系列的理解MVC模式文章中,我们提到MVC的一个重要特征是关注点分离( ...

  4. ASP.NET MVC中使用Ninject

    ASP.NET MVC中使用Ninject 在[ASP.NET MVC 小牛之路]系列上一篇文章(依赖注入(DI)和Ninject)的末尾提到了在ASP.NET MVC中使用Ninject要做的两件事 ...

  5. ASP.NET Core 中的框架级依赖注入

    https://tech.io/playgrounds/5040/framework-level-dependency-injection-with-asp-net-core 作者: Gunnar P ...

  6. 【ASP.NET MVC 学习笔记】- 04 依赖注入(DI)

    本文参考:http://www.cnblogs.com/willick/p/3223042.html 1.在一个类内部,不通过创建对象的实例而能够获得某个实现了公开接口的对象的引用.这种"需 ...

  7. 【ASP.NET MVC 学习笔记】- 05 依赖注入工具Ninject

    本文参考:http://www.cnblogs.com/willick/p/3223042.html 1.Ninject是一款轻量级的DI工具,可通过VS的插件NuGet将其引用到项目中. 2.使用N ...

  8. ASP.NET Web API和ASP.NET Web MVC中使用Ninject

    ASP.NET Web API和ASP.NET Web MVC中使用Ninject 先附上源码下载地址 一.准备工作 1.新建一个名为MvcDemo的空解决方案 2.新建一个名为MvcDemo.Web ...

  9. 在ASP.NET Web API和ASP.NET Web MVC中使用Ninject

    先附上源码下载地址 一.准备工作 1.新建一个名为MvcDemo的空解决方案 2.新建一个名为MvcDemo.WebUI的空MVC应用程序 3.使用NuGet安装Ninject库   二.在ASP.N ...

随机推荐

  1. Spring的IoC容器-Spring ApplicationContext容器

    Application Context是spring中较高级的容器.和BeanFactory类似,它可以加载配置文件中定义的bean,将所有的bean集中在一起,当有请求的时候分配bean. 另外,它 ...

  2. windows 80端口占用情况查询

    在开始-运行,输入CMD打开命令行界面,输入命令 netstat -ano | findstr "80" (注80是你想要看查看的端口号) 就会输出包含80端口使用的情况 具体对应 ...

  3. Python机器学习--降维

    主成分分析(PCA) 测试 # -*- coding: utf-8 -*- """ Created on Thu Aug 31 14:21:51 2017 @author ...

  4. apk解包——修改后缀为zip

    将apk修改后缀为zip后,可直接解包查看资源文件

  5. python web框架企业实战具体解释(第六期)\第三课时-ajax&amp;jquery&amp;webpy

    main.py __author__ = 'Liao' import web import time urls = ( '/gettime','gettime', '/(.*)', 'hello' ) ...

  6. js团购倒计时函数代码

    <h1>团购啦!</h1><p>还剩<span id="times"></span></p> <SCR ...

  7. HDU 2018 母牛的故事 [补]

    今天刚考完试,和杨曙光玩了RPG,实在不想看题了 /***************************************************/ 母牛的故事 Time Limit: 200 ...

  8. C++结构体中使用函数与类中使用函数小结

    #include <iostream>#include <string.h>using namespace std;struct stud//学生信息结构体{    char ...

  9. adb问题整理

    1.开启了两个adb,关掉一个,重启eclipse既可 java.io.IOException: 您的主机中的软件中止了一个已建立的连接. at sun.nio.ch.SocketDispatcher ...

  10. POJ2155 Matrix 二维线段树

    关键词:线段树 二维线段树维护一个 维护一个X线段的线段树,每个X节点维护一个 维护一个Y线段的线段树. 注意,以下代码没有PushDownX.因为如果要这么做,PushDownX时,由于当前X节点的 ...