Autofac的基本使用---3、泛型類型


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<StudentDAL>().As<IStudentDAL>();

c.注冊泛型,這個地方需要把泛型進行注冊,否則無法正常執行

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

  或

  builder.RegisterType<UnitOfWork<AutofacDBEntities>>().As<IUnitOfWork<AutofacDBEntities>>().SingleInstance();

d.生成具體的實例

  var container = builder.Build();

e.在應用運行期間,你需要從容器生命周期域中解析出組件實例來使用它們。

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

f.從容器中解析需要使用的組件

  var iStudentBLL = scope.Resolve<IStudentBLL>();

g.調用解析出來的組件的方法

  List<Student> 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<Apps.Model.Teacher>
@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
</head>
<body>
    <table>
        <tr>
            <th style="width: 400px">主鍵
            </th>
            <th style="width: 80px">姓名
            </th>
            <th style="width: 40px">年齡
            </th>
            <th style="width: 400px">創建時間
            </th>
        </tr>
        @foreach (var item in Model)
        {
            <tr>
                <td style="text-align:center">
                    @Html.DisplayFor(modelItem => item.gKey)
                </td>
                <td style="text-align:center">
                    @Html.DisplayFor(modelItem => item.sName)
                </td>
                <td style="text-align:center">
                    @Html.DisplayFor(modelItem => item.iAge)
                </td>
                <td style="text-align:center">
                    @Html.DisplayFor(modelItem => item.dAddTime)
                </td>
            </tr>
        }
    </table>
</body>
</html>

 

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<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 將容器保存在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<StudentDAL>().As<IStudentDAL>();

c.注冊泛型,這個地方需要把泛型進行注冊,否則無法正常執行

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

  或

  builder.RegisterType<UnitOfWork<AutofacDBEntities>>().As<IUnitOfWork<AutofacDBEntities>>().SingleInstance();

d.注冊Controller,這個有兩個方式。一、手動對項目中所有的Controller進行注冊。二、使用Autofac的方法對程序集中所有的Controller一次性完成注冊

  builder.RegisterType<HomeController>().InstancePerDependency();//手動注冊單個

  或

  builder.RegisterControllers(Assembly.GetExecutingAssembly());//自動注冊全部

e.生成具體的實例

  var container = builder.Build();

f.依賴關系解析.就是使用MVC的擴展 更改了MVC中的注入方式.

  DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

 結果,運行正常。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM