IoC容器Autofac(4) - Autofact + Asp.net MVC + EF Code First(附源码)

本文涉及的产品
容器镜像服务 ACR,镜像仓库100个 不限时长
简介:

本篇文章,讲解如何使用Auotfac, Asp.net MVC和EF Code First,搭建一个松散的架构。 例子代码主要完成的功能是:

列出数据库中Student表中的所有学生信息。

阅读目录:

一、 使用Entity Framework Code First, 写代码创建Student表

二、使用Migrations, 生成数据库和初始化数据

三、创建Controller方法和View

四、正式项目开发中的困境

五、解耦合,脱离数据层

六、实例化,可恶的实例化

七、使用Autofac依赖注入

八、总结

一、使用Entity Framework Code First, 写代码创建Student表

复制代码
 public class SchoolContext : DbContext
    {
        public SchoolContext()
            : base("DefaultConnection")
        {
        }

        public DbSet<Student> Students { get; set; }
    }

    [Table("Student")]
    public class Student
    {
        [Key]
        public int Id { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }
    }
复制代码

二、使用Migrations, 生成数据库和初始化数据

打开"package manager console"

运行Migration, 生成数据库更新代码

会在项目中生成Migrations文件夹,以及2个代码文件。

修改代码, 在Seed方法中,添加程序的初始化数据, 添加3条记录

复制代码
 protected override void Seed(SchoolContext context)
 {
     //  This method will be called after migrating to the latest version.
     //  You can use the DbSet<T>.AddOrUpdate() helper extension method 
    //  to avoid creating duplicate seed data. E.g.
    //
      context.Students.AddOrUpdate(
          s => s.Id,
          new Student {Name = "Andrew Peters", Age = 18},
          new Student {Name = "Brice Lambson", Age = 29},
          new Student {Name = "Rowan Miller", Age = 56}
      );
 }
复制代码

执行"Update-Database"命令,生成和代码匹配的数据库

下图是生成的数据库结果:

三、创建Controller方法和View

controller代码非常简单,如下:

复制代码
 public class HomeController : Controller
    {
        public ActionResult Index()
        {
            var studentRepository = new StudentRepository();
            var students = studentRepository.GetStudents();//调用数据层方法,获取数据
            return View(students);
        }
    }
复制代码

 

最后,运行起来的效果:

 

四、正式项目开发中的困境

假设一个在一个真实的项目环境里面,你和甲一起开发整个项目, 其中甲负责EF数据访问部分,你负责MVC逻辑和显示部分。

在真实项目中当然远远不止Student一个表,可能有上百个,还有很多的存储过程。

你在开发的过程中,常常运行遇到数据层的bug,不断抛出异常,导致你的开发无法顺利进行下去。你常常需要停下来,调试到数据层,找到bug原因,然后告诉甲赶快改好,你还等着开发页面上的一个ajax特效。

随着不断的出现的数据层bug, 眼看项目结束日期越来越近,你已经焦头烂额,但是却还有很多功能没有完成,老板也开始怀疑你的能力..........

 

五、解耦合,脱离数据层

你对甲已经忍无可忍了,你的命运为什么要掌握在甲的手中,要想办法摆脱甲。

好吧,我要依赖在抽象的接口上,而不是直接依赖甲开发的数据层。

首先我们可以创建一个接口:

 public interface IStudentRepository
 {
    IEnumerable<Student> GetStudents();
 }

然后, 创建一个集成这个接口的类,这个类并不访问数据库,但是提供我们开发页面所需的数据。

复制代码
  public class StubStudentRepository:IStudentRepository
  {
        public IEnumerable<Student> GetStudents()
        {
            return new[]
                       {
                           new Student {Id = 1, Name = "Sam", Age = 14}
                       };
        }
  }
复制代码

好了,一切都准备好了, 开始改造我们的Controller代码

复制代码
  public class HomeController : Controller
    {
        public ActionResult Index()
        {
            IStudentRepository studentRepository = new StubStudentRepository();
            //IStudentRepository studentRepository = new StudentRepository();//注释掉访问数据层的代码,用Stub类代替
            var students = studentRepository.GetStudents();
            
            return View(students);
        }
    }
复制代码

由于,我们写的Stub类,不访问数据库,而且不需要有复杂的逻辑,只是提供我们Controller代码运行所需要的基本数据就可以了。这样你的开发就依赖在你自己写的更加可靠的Stub类上了。

最后,你叫来甲,对他说:哥们, 我为我们之间的依赖,创建好了接口,你以后的数据访问代码,都从这个接口继承吧。

从此,这个项目开发变成了另外一种样子,你再也不抱怨甲总是写不稳定的代码了(因为你不依赖他了),你总是能通过写一些Stub类,返回不同的值,来测试你的界面代码。

 六、实例化,可恶的实例化

在Controller的代码中,我们有下面2行代码,如果是发布的情况下,我们使用下面一行,开发过程中,使用上面一行。

但是,这个项目代码太多了,难道到发布的时候,要我一个个找出来,都换成真实的甲的数据库访问层的类的实例吗?

 
 IStudentRepository studentRepository = new StubStudentRepository();
 //IStudentRepository studentRepository = new StudentRepository();//注释掉访问数据层的代码,用Stub类代替
 

七、使用Autofac依赖注入

 这个时候,就是Autofac大显身手的时候了,

首先,我们改造Controller代码:

复制代码
   public class HomeController : Controller
    {
        private readonly IStudentRepository _studentRepository;
        //由构造函数来提供Controller的依赖IStudentRepository
        public HomeController(IStudentRepository studentRepository)
        {
            _studentRepository = studentRepository;
        }

        public ActionResult Index()
        {
            var students = _studentRepository.GetStudents();
            
            return View(students);
        }
    }
复制代码


然后, 修改Global.asax,

复制代码
public class MvcApplication : System.Web.HttpApplication
{
        protected void Application_Start()
        {
            //Autofac初始化过程
            var builder = new ContainerBuilder();
            builder.RegisterControllers(typeof(MvcApplication).Assembly);//注册所有的Controller
            //开发环境下,使用Stub类
            builder.RegisterAssemblyTypes(typeof (MvcApplication).Assembly).Where(
                t => t.Name.EndsWith("Repository") && t.Name.StartsWith("Stub")).AsImplementedInterfaces();
            //发布环境下,使用真实的数据访问层
            //builder.RegisterAssemblyTypes(typeof(MvcApplication).Assembly).Where(
            //   t => t.Name.EndsWith("Repository")).AsImplementedInterfaces();

            var container = builder.Build();
            DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

            //其它的初始化过程
            ........
        }
}
复制代码

当我们使用下面这行代码的时候,所有的controller就都是使用Stub类的实例

//开发环境下,使用Stub类
builder.RegisterAssemblyTypes(typeof (MvcApplication).Assembly).Where(
             t => t.Name.EndsWith("Repository") && t.Name.StartsWith("Stub")).AsImplementedInterfaces();

当我们使用下面代码的时候,所有的controller就都用的是实际的数据访问类实例。

//发布环境下,使用真实的数据访问层
builder.RegisterAssemblyTypes(typeof(MvcApplication).Assembly).Where(t => t.Name.EndsWith("Repository")).AsImplementedInterfaces();

 

八、总结

关于Autofac的详细具体用法,大家可以上官方网站: http://code.google.com/p/autofac/

这里也有文章,对Autofac用法有总结 AutoFac使用方法总结

对于Autofac内部实现的机理, 这里有一篇文章,IoC容器Autofac(3) - 理解Autofac原理,我实现的部分Autofac功能(附源码)

对于Autofac在Asp.net MVC中是如何实现依赖注入的分析,这里有篇文章 分析Autofac如何实现Controller的Ioc(Inversion of Control)

 

其它相关文章

IoC容器Autofac(1) -- 什么是IoC以及理解为什么要使用Ioc

IoC容器Autofac(2) - 一个简单示例(附demo源码)

IoC容器Autofac(3) - 理解Autofac原理,我实现的部分Autofac功能(附源码)

最后,附上本文相关源代码 AutofactMVC.zip使用Nuget, 如果有编译错误, 参照这篇文章 Nuget如何自动下载依赖DLL引用




本文转自JustRun博客园博客,原文链接:http://www.cnblogs.com/JustRun1983/archive/2013/03/28/2981645.html,如需转载请自行联系原作者


目录
相关文章
|
4月前
|
XML Java 数据格式
Spring5入门到实战------7、IOC容器-Bean管理XML方式(外部属性文件)
这篇文章是Spring5框架的实战教程,主要介绍了如何在Spring的IOC容器中通过XML配置方式使用外部属性文件来管理Bean,特别是数据库连接池的配置。文章详细讲解了创建属性文件、引入属性文件到Spring配置、以及如何使用属性占位符来引用属性文件中的值。
Spring5入门到实战------7、IOC容器-Bean管理XML方式(外部属性文件)
|
3月前
|
XML Java 开发者
经典面试---spring IOC容器的核心实现原理
作为一名拥有十年研发经验的工程师,对Spring框架尤其是其IOC(Inversion of Control,控制反转)容器的核心实现原理有着深入的理解。
154 3
|
2月前
|
XML Java 数据格式
Spring IOC容器的深度解析及实战应用
【10月更文挑战第14天】在软件工程中,随着系统规模的扩大,对象间的依赖关系变得越来越复杂,这导致了系统的高耦合度,增加了开发和维护的难度。为解决这一问题,Michael Mattson在1996年提出了IOC(Inversion of Control,控制反转)理论,旨在降低对象间的耦合度,提高系统的灵活性和可维护性。Spring框架正是基于这一理论,通过IOC容器实现了对象间的依赖注入和生命周期管理。
80 0
|
4月前
|
XML Java 数据格式
Spring5入门到实战------3、IOC容器-Bean管理XML方式(一)
这篇文章详细介绍了Spring框架中IOC容器的Bean管理,特别是基于XML配置方式的实现。文章涵盖了Bean的定义、属性注入、使用set方法和构造函数注入,以及如何注入不同类型的属性,包括null值、特殊字符和外部bean。此外,还探讨了内部bean的概念及其与外部bean的比较,并提供了相应的示例代码和测试结果。
Spring5入门到实战------3、IOC容器-Bean管理XML方式(一)
|
4月前
|
XML Java 数据格式
Spring5入门到实战------5、IOC容器-Bean管理(三)
这篇文章深入探讨了Spring5框架中IOC容器的高级Bean管理,包括FactoryBean的使用、Bean作用域的设置、Bean生命周期的详细解释以及Bean后置处理器的实现和应用。
Spring5入门到实战------5、IOC容器-Bean管理(三)
|
4月前
|
XML Java 数据格式
Spring5入门到实战------4、IOC容器-Bean管理XML方式、集合的注入(二)
这篇文章是Spring5框架的实战教程,主题是IOC容器中Bean的集合属性注入,通过XML配置方式。文章详细讲解了如何在Spring中注入数组、List、Map和Set类型的集合属性,并提供了相应的XML配置示例和Java类定义。此外,还介绍了如何在集合中注入对象类型值,以及如何使用Spring的util命名空间来实现集合的复用。最后,通过测试代码和结果展示了注入效果。
Spring5入门到实战------4、IOC容器-Bean管理XML方式、集合的注入(二)
|
4月前
|
XML Java 数据格式
Spring5入门到实战------6、IOC容器-Bean管理XML方式(自动装配)
这篇文章是Spring5框架的入门教程,详细讲解了IOC容器中Bean的自动装配机制,包括手动装配、`byName`和`byType`两种自动装配方式,并通过XML配置文件和Java代码示例展示了如何在Spring中实现自动装配。
Spring5入门到实战------6、IOC容器-Bean管理XML方式(自动装配)
|
4月前
|
XML Java 数据格式
Spring5入门到实战------2、IOC容器底层原理
这篇文章深入探讨了Spring5框架中的IOC容器,包括IOC的概念、底层原理、以及BeanFactory接口和ApplicationContext接口的介绍。文章通过图解和实例代码,解释了IOC如何通过工厂模式和反射机制实现对象的创建和管理,以及如何降低代码耦合度,提高开发效率。
Spring5入门到实战------2、IOC容器底层原理
|
4月前
|
开发框架 .NET 数据库连接
闲话 Asp.Net Core 数据校验(三)EF Core 集成 FluentValidation 校验数据例子
闲话 Asp.Net Core 数据校验(三)EF Core 集成 FluentValidation 校验数据例子
100 1
|
4月前
|
Java Spring 容器
建模底层逻辑问题之以Spring IOC容器为例,使用因果法建模,如何操作
建模底层逻辑问题之以Spring IOC容器为例,使用因果法建模,如何操作