IoC~MVC3+EF+Autofac实现松耦合的系统架构 [转载]
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的对象,这一点是需要注意的。