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

在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. PERL 源码 大神网站

    http://blog.csdn.net/haoyujie/article/category/1187883 http://deepfuture.iteye.com/blog/816428

  2. send to instance already dealloc nil error

    这个是因为发送消息的对象已经被dealloc了,然后再次发送[release]请求就不行了.所以可以retain或者alloc对象 if (self.buttonsList) {            ...

  3. 【spring boot jpa】hql语句报错 :antlr.NoViableAltException: unexpected token: roleName

    使用场景:在spring data jpa下使用@Query("hql语句") 然后在项目启动的时候报错 hql语句报错:antlr.NoViableAltException: u ...

  4. booth乘法器原理

    在微处理器芯片中,乘法器是进行数字信号处理的核心,同一时候也是微处理器中进行数据处理的wd=%E5%85%B3%E9%94%AE%E9%83%A8%E4%BB%B6&hl_tag=textli ...

  5. Solidworks如何绘制装饰螺纹线

    1 插入-注解,装饰螺纹线   2 绘制装饰螺纹线,选择螺纹的边线,标准选择ISO,下面可以选择的范围就确定了(M6的孔,只能选择M8的螺纹或者M10的螺纹),画好之后在3D图中并没有明确的螺纹样式 ...

  6. HTML小知识点积累

    1.怎样让heigth:100%起效?   有时候我们设置heigth:100%,想让当前控件铺满整个屏幕,可是非常少情况下这个属性能达到我们想要的效果,这是为什么呢?   而依据W3C的规范.百分比 ...

  7. C语言使用以及其它语言经常出的错误

    1. 计算优先级 i/*pi/(*p) //默认即用“()”花括号分隔即可 2.分号结束 ; ; if(i<j);{ //code } //分号结束必须看清楚 3.声明变量 ; ; //声明变量 ...

  8. js 验证 输入值 全是数字

    1.使用isNaN()函数 isNaN()的缺点就在于 null.空格以及空串会被按照0来处理 NaN: Not a Number /** *判断是否是数字 **/ function isRealNu ...

  9. win32收不到F10按键消息解决的方法

    在WM_KEYDOWN中处理F10(VK_F10)消息总是获取不到,后来用spy++监听窗体消息发现按下F10并没有WM_KEYDOWN消息产生,而是产生了WM_SYSKEYDOWN

  10. Mmseg中文分词算法解析

    Mmseg中文分词算法解析 @author linjiexing 开发中文搜索和中文词库语义自己主动识别的时候,我採用都是基于mmseg中文分词算法开发的Jcseg开源project.使用场景涉及搜索 ...