准備
使用的表是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));
結果,運行正常。