MVC3+EF+Autofac網上這種文章確實沒有,呵呵,今天就寫一個,代大家分享!
這個系列的文章將帶我們進入一種新的開發模式,注入開發模式,或者叫它IOC模式,說起IOC你可以這樣去理解它,它為你的某個實現流出一個注入點,你生產的對象,可以根據你之前的配置進行組合,這是可以的。而注入點的位置及方式也是多種多樣的,我們今天主要說一個通過HTTP請求進行注入的方式,IOC工具使用高效的
Autofac,對它的認識你可以看這篇文章。
首先看一下我們這個項目的知識點:
MVC3~一個對UI層進行分層的架構模式,在微軟的MVC3中加入了開源的Razor引擎
EF~這無疑是微軟自己比較成功的ORM工具,它執行效率上要高於linq to sql,甚至你自己編寫的ado.net腳本。
Autofac~這是在orchard項目中被廣泛的IoC工具,它支持類型,反泛,HTTP等注入
對於這個系統的autofac部分,我們將它的注入點放在controller的構造函數中,將生產的對象配置在global中,當然,你也可以設置在config文件,或者你自己的XML文件。
我認為它的工作方式應該是:
網站啟動=>從global中得到ioc配置信息=>http request請求頁面=>通過controller中的參數進行實現的創建=>action中使用創建好的對象
OK,有了這樣一個理論基礎,我們來看一下代碼吧:
EF部分的DATA層
1 /// <summary> 2 /// EF數據結構實現 3 /// </summary> 4 /// <typeparam name="T"></typeparam> 5 public class Repository<T> : IRepository<T> where T : class 6 { 7 private readonly DbContext _db; 8 9 public Repository() 10 { 11 Logger = NullLogger.Instance; 12 _db = new EEE114Entities(); 13 } 14 15 public ILogger Logger { get; set; } 16 #region IRepository<T> 成員 17 List<string> _columns; 18 public Repository<T> AddColumn(Func<string> func) 19 { 20 _columns.Add(func()); 21 return this; 22 } 23 #region Create,Update,Delete 24 public virtual void Create(T entity) 25 { 26 Logger.Debug("Create {0}", entity); 27 _db.Entry<T>(entity); 28 _db.Set<T>().Add(entity); 29 } 30 31 public virtual void Update(T entity) 32 { 33 Logger.Debug("Update {0}", entity); 34 _db.Set<T>().Attach(entity); 35 var ObjectStateEntry = ((IObjectContextAdapter)_db).ObjectContext.ObjectStateManager.GetObjectStateEntry(entity); 36 string[] p = { }; 37 Array.ForEach(p, x => 38 { 39 ObjectStateEntry.SetModifiedProperty(x.Trim()); 40 }); 41 } 42 43 public virtual void Delete(T entity) 44 { 45 Logger.Debug("Delete {0}", entity); 46 _db.Set<T>().Attach(entity); 47 _db.Set<T>().Remove(entity); 48 } 49 50 public virtual void SaveChanges() 51 { 52 try 53 { 54 _db.SaveChanges(); 55 } 56 catch (System.Data.Entity.Infrastructure.DbUpdateException ex) 57 { 58 string Message = "error:"; 59 if (ex.InnerException == null) 60 Message += ex.Message + ","; 61 else if (ex.InnerException.InnerException == null) 62 Message += ex.InnerException.Message + ","; 63 else if (ex.InnerException.InnerException.InnerException == null) 64 Message += ex.InnerException.InnerException.Message + ","; 65 throw new Exception(Message); 66 } 67 } 68 #endregion 69 70 #region Get 71 public virtual int Count(Expression<Func<T, bool>> predicate) 72 { 73 return Fetch(predicate).Count(); 74 } 75 public T Get(params object[] id) 76 { 77 throw new NotImplementedException(); 78 } 79 public virtual T Get(Expression<Func<T, bool>> predicate) 80 { 81 return Fetch(predicate).SingleOrDefault(); 82 } 83 public IQueryable<T> Table 84 { 85 get { return _db.Set<T>(); } 86 } 87 88 public IEnumerable<T> Fetch(Expression<Func<T, bool>> predicate) 89 { 90 return Table.Where(predicate); 91 } 92 93 public IEnumerable<T> Fetch(Expression<Func<T, bool>> predicate, Action<Orderable<T>> order) 94 { 95 var orderable = new Orderable<T>(Fetch(predicate).AsQueryable()); 96 order(orderable); 97 return orderable.Queryable; 98 } 99 100 public IEnumerable<T> Fetch(Expression<Func<T, bool>> predicate, Action<Orderable<T>> order, int skip, int count) 101 { 102 return Fetch(predicate, order).Skip(skip).Take(count); 103 } 104 #endregion 105 106 #endregion 107 }
Services層(BLL層)核心代碼:
1 /// <summary> 2 /// 網站異常業務 3 /// </summary> 4 public class Web_ExceptionLogManager : IWeb_ExceptionLogManager 5 { 6 IRepository<Web_ExceptionLog> _web_ExceptionLogRepository; 7 public Web_ExceptionLogManager(IRepository<Web_ExceptionLog> web_ExceptionLogRepository) 8 { 9 _web_ExceptionLogRepository = web_ExceptionLogRepository; 10 } 11 #region IWeb_ExceptionLogManager 成員 12 13 public List<Web_ExceptionLog> GetWeb_ExceptionLog() 14 { 15 return _web_ExceptionLogRepository.Fetch(i => i.FullInfo != null, i => i.Asc(j => j.OccurTime)).ToList(); 16 17 } 18 19 #endregion 20 }
WEB層MVC部分代碼:
1 public class HomeController : Controller 2 { 3 IRepository<Web_Logs> _iRepository; 4 IWeb_ExceptionLogManager _web_ExceptionLogManager; 5 6 public HomeController(IRepository<Web_Logs> iRepository, IWeb_ExceptionLogManager web_ExceptionLogManager) 7 { 8 _iRepository = iRepository; 9 _web_ExceptionLogManager = web_ExceptionLogManager; 10 } 11 12 public ActionResult Index(int sort = 1) 13 { 14 ViewBag.Message = "歡迎使用 ASP.NET MVC!"; 15 16 var model = _iRepository.Fetch(i => i.Info != null, i => i.Asc(j => j.OccurTime)); 17 if (sort != 1) 18 model = _iRepository.Fetch(i => i.Info != null, i => i.Desc(j => j.OccurTime)); 19 20 ViewBag.Log = _web_ExceptionLogManager.GetWeb_ExceptionLog(); 21 return View(model); 22 }
而注入參數我們放在global中,看一下核心代碼:
1 protected void Application_Start() 2 { 3 #region Autofac注入 4 var builder = new ContainerBuilder(); 5 builder.RegisterControllers(Assembly.GetExecutingAssembly()); 6 builder.RegisterGeneric(typeof(Repository<>)).As(typeof(IRepository<>)).InstancePerHttpRequest(); 7 8 builder.RegisterType<Web_ExceptionLogManager>().As<IWeb_ExceptionLogManager>().InstancePerHttpRequest(); //從HTTP請求中重到注入點 9 10 IContainer container = builder.Build(); 11 DependencyResolver.SetResolver(new AutofacDependencyResolver(container)); 12 #endregion 13 14 AreaRegistration.RegisterAllAreas(); 15 RegisterGlobalFilters(GlobalFilters.Filters); 16 RegisterRoutes(RouteTable.Routes); 17 }
OK,我們運行后,在/Home/Index中自己運行HTTP請求把global中的對象進行創建,當然,它在創建對象時,你可以是DATA層,或者是SERVICE層的,這里
沒有考慮WEB不能與DATA通訊問題,實際項目中,我們的WEB層不應該有對DATA層的引用,所以,WEB層一般只注入SERVICE的對象,這一點是需要注意的。