Autofac的基本使用---3、泛型类型
阅读原文时间:2023年07月10日阅读:1

Autofac的基本使用---目录

使用的表是Teacher,创建相关的IDAL、DAL、IBLL、BLL层。

使用EF,创建一个Model层,存放edmx文件。

创建一个Infrastructure层,基础设施项目,使用泛型类型。

控制台程序的使用

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Apps.BLL;
using Apps.DAL;
using Apps.IBLL;
using Apps.IDAL;
using Apps.Infrastructure.BaseObject;
using Apps.Infrastructure.IBaseInterface;
using Apps.Model;
using Autofac;

namespace Apps.Con
{
class Program
{
static void Main(string[] args)
{
#region 普通类型---Student
//// 创建组件/服务注册的容器
//var builder = new ContainerBuilder();

        //// 注册类型公开接口  
        //builder.RegisterType<StudentDAL>().As<IStudentDAL>();  
        //// builder.RegisterType<StudentDAL>().AsSelf().As<IStudentDAL>();  
        //builder.RegisterType<StudentBLL>().As<IStudentBLL>();

        //// 编译容器完成注册且准备对象解析  
        //var container = builder.Build();

        //// 现在你可以使用 Autofac 解析服务. 例如,这行将执行注册的lambda表达式对于 IConfigReader 服务.  
        ////但是我们不推荐直接操作容器,这会导致内存泄漏。  
        ////当我们解析出一个组件时,依赖于我们定义的lifetime scope,一个新的对象实例会被创建。  
        //using (var scope = container.BeginLifetimeScope())  
        //{  
        //    //从容器中解析需要使用的组件  
        //    var iStudentBLL = scope.Resolve<IStudentBLL>();  
        //    //调用解析后的组件中的方法  
        //    List<Student> list = iStudentBLL.GetList().ToList();

        //    Console.WriteLine("List中的数据行:" + list.Count);  
        //}  
        #endregion

        #region 泛型类型---Teacher  
        // 创建组件/服务注册的容器  
        var builder = new ContainerBuilder();

        // 注册类型公开接口  
        builder.RegisterType<TeacherDAL>().As<ITeacherDAL>();  
        builder.RegisterType<TeacherBLL>().As<ITeacherBLL>();  
        //方式1.以泛型方式注册  
        builder.RegisterGeneric(typeof(UnitOfWork<>)).As(typeof(IUnitOfWork<>)).SingleInstance();  
        builder.RegisterGeneric(typeof(DatabaseFactory<>)).As(typeof(IDatabaseFactory<>)).SingleInstance();

        //方式2.以普通的方式注册  
        //builder.RegisterType<UnitOfWork<AutofacDBEntities>>().As<IUnitOfWork<AutofacDBEntities>>().SingleInstance();  
        //builder.RegisterType<DatabaseFactory<AutofacDBEntities>>().As<IDatabaseFactory<AutofacDBEntities>>().SingleInstance();

        // 编译容器完成注册且准备对象解析  
        var container = builder.Build();

        // 现在你可以使用 Autofac 解析服务. 例如,这行将执行注册的lambda表达式对于 IConfigReader 服务.  
        //但是我们不推荐直接操作容器,这会导致内存泄漏。  
        //当我们解析出一个组件时,依赖于我们定义的lifetime scope,一个新的对象实例会被创建。  
        using (var scope = container.BeginLifetimeScope())  
        {  
            //从容器中解析需要使用的组件  
            var iTeacherBLL = scope.Resolve<ITeacherBLL>();  
            //调用解析后的组件中的方法

            List<Teacher> list = iTeacherBLL.GetList(t => t.gKey != null).ToList();  
            Console.WriteLine("List中的数据行:" + list.Count);

            //Teacher model = iTeacherBLL.GetModelByCondition(t => t.iAge == 5);  
            //model.dAddTime = DateTime.Now;  
            //iTeacherBLL.Update();

            Teacher model = new Teacher();  
            model.gKey = Guid.NewGuid();  
            model.iAge = 12;  
            model.sName = "郭彤";  
            model.dAddTime = DateTime.Now;  
            Console.WriteLine(iTeacherBLL.Add(model));  
        }  
        #endregion

        Console.ReadKey();  
    }  
}  

}

(1)使用流程

a.参见Autofac管理注册类的容器实例

  var builder = new ContainerBuilder();

b.下面就需要为这个容器注册它可以管理的类型

  builder.RegisterType().As();

c.注册泛型,这个地方需要把泛型进行注册,否则无法正常执行

  builder.RegisterGeneric(typeof(UnitOfWork<>)).As(typeof(IUnitOfWork<>)).SingleInstance();

  或

  builder.RegisterType>().As>().SingleInstance();

d.生成具体的实例

  var container = builder.Build();

e.在应用运行期间,你需要从容器生命周期域中解析出组件实例来使用它们。

  using (var scope = container.BeginLifetimeScope())  {  }

f.从容器中解析需要使用的组件

  var iStudentBLL = scope.Resolve();

g.调用解析出来的组件的方法

  List list = iStudentBLL.GetList().ToList();

(2)中间碰到的问题。

在(1)的c.注册泛型,这个地方需要把泛型进行注册,否则无法正常执行 步骤时,

开始的注册代码是:builder.RegisterGeneric(typeof(UnitOfWork<>)).As(typeof(IUnitOfWork<>));

也就是没有带最后面的.SingleInstance();方法。

此时测试时,是能获取到数据的,

但是,当新增修改删除数据时,却无法进行。

单步调试发现,UnitOfWork中的数据库上下文对象中的实体是空的。

想起之前看到网上大神说的,UnitOfWork就是保证在操作数据时使用的是同一个状态下的数据库,以保证数据的一致性。

猜测,Autofac的配置有问题,我没有获取到同一个操作数据库的对象导致。

于是,百度相关的问题。在大佬网页:https://www.cnblogs.com/jys509/p/4649798.html

找到了这么个配置,然后在注册组件时加上这个方法,再进行测试时 新增修改数据就成功了。

MVC中的使用

@model List
@{
Layout = null;
}

Index

@foreach (var item in Model) { }
主键 姓名 年龄 创建时间
@Html.DisplayFor(modelItem => item.gKey) @Html.DisplayFor(modelItem => item.sName) @Html.DisplayFor(modelItem => item.iAge) @Html.DisplayFor(modelItem => item.dAddTime)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Apps.IBLL;
using Apps.Model;
using Autofac;
using Autofac.Core;

namespace Apps.Web.Controllers
{
public class HomeController : Controller
{
#region 普通类型---Student
//private readonly IStudentBLL _iBLL;
//public HomeController(IStudentBLL iBLL)
//{
// this._iBLL = iBLL;
//}
//public ActionResult Index()
//{
// List lstStudent = _iBLL.GetList().ToList();

    //    //为了视图不要重写,将Student类赋值给Teacher类。两个类的字段完全一样  
    //    List<Teacher> lstTeacher = new List<Teacher>();  
    //    foreach (Student item in lstStudent)  
    //    {  
    //        Teacher model = new Teacher();  
    //        model.gKey = item.gKey;  
    //        model.sName = item.sName;  
    //        model.iAge = item.iAge;  
    //        model.dAddTime = item.dAddTime;  
    //        lstTeacher.Add(model);  
    //    }

    //    return View(lstTeacher);  
    //}  
    #endregion

    #region 将容器保存在Application中---Student  
    //private IStudentBLL \_iBLL;  
    //public ActionResult Index()  
    //{  
    //    if (\_iBLL == null)  
    //    {  
    //        object oContainer = System.Web.HttpContext.Current.Application\["container"\];  
    //        if (oContainer != null && oContainer != "")  
    //        {  
    //            IContainer ioc = (IContainer)oContainer;  
    //            //当我们解析出一个组件时,依赖于我们定义的lifetime scope,一个新的对象实例会被创建。  
    //            using (var scope = ioc.BeginLifetimeScope())  
    //            {  
    //                //从容器中解析需要使用的组件  
    //                \_iBLL = scope.Resolve<IStudentBLL>();  
    //                //调用解析后的组件中的方法  
    //                List<Student> list = \_iBLL.GetList().ToList();

    //                Console.WriteLine("List中的数据行:" + list.Count);  
    //            }  
    //        }  
    //        else  
    //        {  
    //            throw new Exception("IOC容器初始化发生错误!");  
    //        }  
    //    }  
    //    List<Student> lstStudent = \_iBLL.GetList().ToList();

    //    //为了视图不要重写,将Student类赋值给Teacher类。两个类的字段完全一样  
    //    List<Teacher> lstTeacher = new List<Teacher>();  
    //    foreach (Student item in lstStudent)  
    //    {  
    //        Teacher model = new Teacher();  
    //        model.gKey = item.gKey;  
    //        model.sName = item.sName;  
    //        model.iAge = item.iAge;  
    //        model.dAddTime = item.dAddTime;  
    //        lstTeacher.Add(model);  
    //    }

    //    return View(lstTeacher);  
    //}  
    #endregion

    #region 泛型类型---Teacher  
    private readonly ITeacherBLL \_iBLL;  
    public HomeController(ITeacherBLL iBLL)  
    {  
        this.\_iBLL = iBLL;  
    }  
    public ActionResult Index()  
    {  
        List<Teacher> lstStudent = \_iBLL.GetList(t => t.gKey != null).ToList();

        Teacher model1 = \_iBLL.GetModelByCondition(t => t.iAge == 5);  
        model1.dAddTime = DateTime.Now;  
        \_iBLL.Update();

        //Teacher model = new Teacher();  
        //model.gKey = Guid.NewGuid();  
        //model.iAge = 12;  
        //model.sName = "郭彤";  
        //model.dAddTime = DateTime.Now;  
        //\_iBLL.Add(model);

        return View(lstStudent);  
    }  
    #endregion  
}  

}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using Apps.BLL;
using Apps.DAL;
using Apps.IBLL;
using Apps.IDAL;
using Apps.Infrastructure.BaseObject;
using Apps.Infrastructure.IBaseInterface;
using Apps.Web.Controllers;
using Autofac;
using Autofac.Integration.Mvc;

namespace Apps.Web
{
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RouteConfig.RegisterRoutes(RouteTable.Routes);

        #region 普通类型---Student  
        //// 创建组件/服务注册的容器  
        //var builder = new ContainerBuilder();

        //// 注册类型公开接口  
        //builder.RegisterType<StudentDAL>().As<IStudentDAL>();  
        //builder.RegisterType<StudentBLL>().As<IStudentBLL>();

        ////方式1:单个Controller的注册(项目中有多少个Controller就要写多少次)  
        //builder.RegisterType<HomeController>().InstancePerDependency();  
        ////方式2:使用Autofac提供的RegisterControllers扩展方法来对程序集中所有的Controller一次性的完成注册  
        ////builder.RegisterControllers(Assembly.GetExecutingAssembly());

        ////生成具体的实例  
        //var container = builder.Build();  
        ////下面就是使用MVC的扩展 更改了MVC中的注入方式.  
        //DependencyResolver.SetResolver(new AutofacDependencyResolver(container));  
        #endregion

        #region 将容器保存在Application中---Student  
        //// 创建组件/服务注册的容器  
        //var builder = new ContainerBuilder();

        //// 注册类型公开接口  
        //builder.RegisterType<StudentDAL>().As<IStudentDAL>();  
        //builder.RegisterType<StudentBLL>().As<IStudentBLL>();

        ////方式1:单个Controller的注册(项目中有多少个Controller就要写多少次)  
        ////builder.RegisterType<HomeController>().InstancePerDependency();  
        ////方式2:使用Autofac提供的RegisterControllers扩展方法来对程序集中所有的Controller一次性的完成注册  
        ////builder.RegisterControllers(Assembly.GetExecutingAssembly());

        ////生成具体的实例  
        //var container = builder.Build();  
        ////下面就是使用MVC的扩展 更改了MVC中的注入方式.  
        ////DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

        //Application.Add("container", container);  
        #endregion

        #region 泛型类型---Teacher  
        // 创建组件/服务注册的容器  
        var builder = new ContainerBuilder();

        // 注册类型公开接口

        builder.RegisterGeneric(typeof(UnitOfWork<>)).As(typeof(IUnitOfWork<>)).SingleInstance();  
        builder.RegisterGeneric(typeof(DatabaseFactory<>)).As(typeof(IDatabaseFactory<>)).SingleInstance();

        builder.RegisterType<TeacherBLL>().As<ITeacherBLL>();  
        builder.RegisterType<TeacherDAL>().As<ITeacherDAL>();

        //方式1:单个Controller的注册(项目中有多少个Controller就要写多少次)  
        //builder.RegisterType<HomeController>().InstancePerDependency();  
        //方式2:使用Autofac提供的RegisterControllers扩展方法来对程序集中所有的Controller一次性的完成注册  
        builder.RegisterControllers(Assembly.GetExecutingAssembly());

        //生成具体的实例  
        var container = builder.Build();  
        //下面就是使用MVC的扩展 更改了MVC中的注入方式.  
        DependencyResolver.SetResolver(new AutofacDependencyResolver(container));  
        #endregion  
    }  
}  

}

前面两个Index.cshtml和HomeCotroller.cs只是数据的展示,所以被折叠起来。

重点在Global.asax中的配置。

(1)使用流程

自己理解

a.参见Autofac管理注册类的容器实例

  var builder = new ContainerBuilder();

b.下面就需要为这个容器注册它可以管理的类型

  builder.RegisterType().As();

c.注册泛型,这个地方需要把泛型进行注册,否则无法正常执行

  builder.RegisterGeneric(typeof(UnitOfWork<>)).As(typeof(IUnitOfWork<>)).SingleInstance();

  或

  builder.RegisterType>().As>().SingleInstance();

d.注册Controller,这个有两个方式。一、手动对项目中所有的Controller进行注册。二、使用Autofac的方法对程序集中所有的Controller一次性完成注册

  builder.RegisterType().InstancePerDependency();//手动注册单个

  或

  builder.RegisterControllers(Assembly.GetExecutingAssembly());//自动注册全部

e.生成具体的实例

  var container = builder.Build();

f.依赖关系解析.就是使用MVC的扩展 更改了MVC中的注入方式.

  DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

结果,运行正常。