Document

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的对象,这一点是需要注意的。

 

posted @ 2017-01-13 18:10  从未被超越  阅读(333)  评论(0编辑  收藏  举报