Autofac3 在MVC4中的運用原理


    這是一種新的開發模式,注入開發模式,或者叫它IOC模式,說起IOC你可以這樣去理解它,它為你的某個實現流出一個注入點,你生產的對象,可以根據你之前的配置進行組合。  IOC全稱是Inversion of Control,即反轉控制,或者說是依賴注入更為合適。選擇別糾結這些全稱的專業詞。我們可以用別外一些方式去理解它,IOC,是一種設計模式。它的延生所要實現的是把藕合從代碼中移出去,統一放到XML文件中,通過一個容器在需要的時候把這個依賴關系形成,即把需要的接口實現注入到需要它的類中,這可能就是“依賴注入”說法的來源了。 

而注入點的位置及方式也是多種多樣的,我們今天主要說一個通過HTTP請求進行注入的方式,IOC工具使用高效的Autofac,對它的認識你可以看這篇文章。


首先看一下我們這個項目的知識點:
MVC4一個對UI層進行分層的架構模式,在微軟的MVC4中加入了開源的Razor引擎
EF(Entity Framework)這無疑是微軟自己比較成功的ORM(Object Relational Mapping)工具(即對象關系映射,目前數據庫是關系型數據庫ORM 主要是把數據庫中的關系數據映射稱為程序中的對象),它執行效率上要高於linq to sql,甚至你自己編寫的ado.net腳本。
Autofac這是在orchard項目中被廣泛的IOC工具,它支持類型,反泛,HTTP等注入
對於這個系統的autofac部分,我們將它的注入點放在controller的構造函數中,將生產的對象配置在global中,當然,你也可以設置在config文件,或者你自己的文件中。
我認為它的工作方式應該是:
網站啟動=>從global中得到ioc配置信息=>http request請求頁面=>通過controller中的參數進行實現的創建=>action中使用創建好的對象

OK,有了這樣一個理論基礎,我們來看一下代碼吧:

EF部分的DATA層

  1  public partial class EfRepository<T> : IRepository<T> where T : class  2     {
  3         private readonly Guid _instanceId;
  4         private readonly IDbContext _context;
  5         private IDbSet<T> _entities;
  6         public Guid InstanceId
  7         {
  8             get { return _instanceId; }
  9         }
 10         public EfRepository(IDbContext context)
 11         {
 12             AutoCommitEnabled = true;
 13             this._context = context;
 14             _instanceId = Guid.NewGuid();
 15         }
 16         public T GetById(object id)
 17         {
 18             return this._entities.Find(id);
 19         }
 20         public T Create()
 21         {
 22             return this.Entities.Create();
 23         }
 24         public void Insert(T entity)
 25         {
 26             try
 27             {
 28                 if (entity == null)
 29                     throw new ArgumentNullException("entity");
 30                 this.Entities.Add(entity);
 31                 if (this.AutoCommitEnabled)
 32                     _context.SaveChanges();
 33             }
 34             catch(DbEntityValidationException dbEx)
 35             {
 36                 var msg = string.Empty;
 37                 foreach(var validationErrors in dbEx.EntityValidationErrors)
 38                     foreach (var validationError in validationErrors.ValidationErrors)
 39                         msg += string.Format("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage) + Environment.NewLine;
 40                 var fail = new Exception(msg, dbEx);
 41                 throw fail;
 42             }
 43         }
 44 
 45         public void InsertRange(IEnumerable<T> entities, int batchSize = 100)
 46         {
 47             try
 48             {
 49                 if (entities == null)
 50                     throw new ArgumentNullException("entities");
 51                 if (entities.HasItems())
 52                 {
 53                     if (batchSize <= 0)
 54                     {
 55                         entities.Each(x => this.Entities.Add(x));
 56                         if (this.AutoCommitEnabled)
 57                             _context.SaveChanges();
 58                     }
 59                     else
 60                     {
 61                         int i = 1;
 62                         bool saved = false;
 63                         foreach (var entity in entities)
 64                         {
 65                             this.Entities.Add(entity);
 66                             saved = false;
 67                             if (i % batchSize == 0)
 68                             {
 69                                 if (this.AutoCommitEnabled)
 70                                     _context.SaveChanges();
 71                                 i = 0;
 72                                 saved = true;
 73                             }
 74                             i++;
 75                         }
 76                         if (!saved)
 77                         {
 78                             if (this.AutoCommitEnabled)
 79                                 _context.SaveChanges();
 80                         }
 81                     }
 82                 }
 83             }
 84             catch (DbEntityValidationException ex)
 85             {
 86                 throw ex;
 87             }
 88         }
 89         public void Update(T entity)
 90         {
 91             if (entity == null)
 92                 throw new ArgumentNullException("entity");
 93             try
 94             {
 95                 if (this.InternalContext.Entry(entity).State == EntityState.Detached)
 96                 {
 97                     var set = Entities;
 98                     T attachedEntity = set.Find(entity.Key);  // You need to have access to key
 99 
100                     if (attachedEntity != null)
101                     {
102                         var attachedEntry = this.InternalContext.Entry(attachedEntity);
103                         attachedEntry.CurrentValues.SetValues(entity);
104                     }
105                     else
106                     {
107                         // This should attach entity
108                         this.InternalContext.Entry(entity).State = EntityState.Modified;
109                     }
110                 }
111             }
112             finally { }
113 
114             if (AutoCommitEnabled)
115                 _context.SaveChanges();
116         }
117 
118         public void Delete(T entity)
119         {
120             if (entity == null)
121                 throw new ArgumentNullException("entity");
122             if(InternalContext.Entry(entity).State==EntityState.Detached)
123             {
124                 this.Entities.Attach(entity);
125             }
126             this.Entities.Remove(entity);
127             if (this.AutoCommitEnabled)
128                 _context.SaveChanges();
129         }
130 
131         public IDictionary<string, object> GetModifiedProperties(T entity)
132         {
133             var props = new Dictionary<string, object>();
134 
135             var ctx = InternalContext;
136             var entry = ctx.Entry(entity);
137             var modifiedPropertyNames = from p in entry.CurrentValues.PropertyNames
138                                         where entry.Property(p).IsModified
139                                         select p;
140             foreach (var name in modifiedPropertyNames)
141             {
142                 props.Add(name, entry.Property(name).OriginalValue);
143             }
144 
145             return props;
146         }
147         public virtual IQueryable<T> Table
148         {
149             get
150             {
151                 return this.Entities;
152             }
153         }
154 
155         public int Commit()
156         {
157             try
158             {
159                 return this._context.SaveChanges();
160             }
161             catch(DbEntityValidationException dbEx)
162             {
163                 var msg = string.Empty;
164                 foreach (var validationErrors in dbEx.EntityValidationErrors)
165                     foreach (var validationError in validationErrors.ValidationErrors)
166                         msg += Environment.NewLine + string.Format("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage);
167 
168                 var fail = new Exception(msg, dbEx);
169                 throw fail;
170             }
171         }
172         #region Helpers
173         protected internal dwDbContextBase InternalContext
174         {
175             get { return _context as dwDbContextBase; }
176         }
177         public bool AutoCommitEnabled { get; set; }
178 
179         private DbSet<T> Entities
180         {
181             get
182             {
183                 if (_entities == null) { _entities = _context.Set<T>(); }
184                 return _entities as DbSet<T>;
185             }
186         }
187 
188         #endregion
189 
190         public IQueryable<T> Include(IQueryable<T> query,string path)
191         {
192             Guard.ArgumentNotNull(query, "query");
193             Guard.ArgumentNotEmpty(path, "path");
194             return query.Include(path);
195         }
196         public IQueryable<T> Include<TProperty>(IQueryable<T> query,Expression<Func<T,TProperty>> path)
197         {
198             Guard.ArgumentNotNull(query, "query");
199             Guard.ArgumentNotNull(path, "path");
200             return query.Include(path);
201         }
202         public IDbContext Context
203         {
204             get { return _context; }
205         }
206 
207     }

 Services層(BLL層)核心代碼:

 1   public class TestService : BaseService, ITestService
 2     {
 3         private const string IncludeProperties = "";
 4         private readonly IRepository<Tests> _repository;
 5         private readonly ICacheManager _cacheManager;
 6         private readonly IExporter _exporter;
 7         public IList<Tests> GetAll()
 8         {
 9             return _repository.FindBy(null, null, IncludeProperties).ToList();
10         }
11 
12         public TestService(IRepository<Tests> repository,
13             ICacheManager cacheManager,IExporter exporter,
14             IEventPublisher eventPublisher):base(eventPublisher)
15         {
16             _repository = repository;
17             _exporter = exporter;
18             _cacheManager = cacheManager;
19         }
20 
21     }

WEB層MVC部分代碼:(注意:我們的WEB層不應該有對DATA層的引用,WEB層一般只注入SERVICE的對象,這一點是需要注意的,即不要直接調用數據庫倉庫)

 public class TestController : ApiController
    {
        private readonly ITestService _service;
        private readonly Func<Tests, TestsModel, TestsModel> _convertCallback = (entity, model) => { return model; };
        public TestController(ITestService service) { _service = service; }
        public IEnumerable<TestsModel> Get()
        {
            var items = _service.GetAll();
            var model = items.ConvertTo(_convertCallback);
            return model;
        }

而注入參數我們放在global中,看一下核心代碼:

            //初始化依賴注入組件
            var bootStrapper = new AutofacBootStrapper();
            BootStrapperManager.Initialize(bootStrapper);
            //設置依賴注入
            GlobalConfiguration.Configuration.DependencyResolver = bootStrapper.GetWebApiDependencyResolver();
            DependencyResolver.SetResolver(bootStrapper.GetMvcDependencyResolver());
 builder.Register(c => new dwObjectContext("MyConnection")).As<IDbContext>().InstancePerHttpRequest().InstancePerApiRequest();
            builder.RegisterGeneric(typeof(EfRepository<>)).As(typeof(IRepository<>)).InstancePerHttpRequest().InstancePerApiRequest();

            //注冊緩存類型
            builder.RegisterType<StaticCache>().As<ICache>().Named<ICache>(YB_CACHE_STATIC).SingleInstance();
            builder.RegisterType<RequestCache>().As<ICache>().Named<ICache>(YB_CACHE_PER_REQUEST).InstancePerHttpRequest().InstancePerApiRequest();
            //注冊緩存控制類型
            builder.RegisterType<NullCacheManager>()
                .As<ICacheManager>()
                .Named<ICacheManager>(YB_SM_CACHE_NULL)
                .WithParameter(ResolvedParameter.ForNamed<ICache>(YB_CACHE_STATIC))
                .SingleInstance();

            builder.RegisterType<DefaultCacheManager>()
                .As<ICacheManager>()
                .Named<ICacheManager>(YB_SM_CACHE_PER_REQUEST)
                .WithParameter(ResolvedParameter.ForNamed<ICache>(YB_CACHE_PER_REQUEST))
                .InstancePerHttpRequest().InstancePerApiRequest();

            builder.RegisterType<DefaultCacheManager>()
               .As<ICacheManager>()
                //.Named<ICacheManager>(YB_SM_CACHE_STATIC)
               .WithParameter(ResolvedParameter.ForNamed<ICache>(YB_CACHE_STATIC))
               .SingleInstance();

            var assembly = Assembly.GetExecutingAssembly();
            //注冊所有 MVC 控制器
            builder.RegisterControllers(assembly)
                .InstancePerHttpRequest();
            //注冊所有 Web Api 控制器
            builder.RegisterApiControllers(assembly)
                .InstancePerApiRequest();

 


免責聲明!

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



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