zoukankan      html  css  js  c++  java
  • 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();
  • 相关阅读:
    1052 Linked List Sorting (25 分)
    1051 Pop Sequence (25 分)
    1050 String Subtraction (20 分)
    1049 Counting Ones (30 分)
    1048 Find Coins (25 分)
    1047 Student List for Course (25 分)
    1046 Shortest Distance (20 分)
    1045 Favorite Color Stripe (30 分)
    1044 Shopping in Mars (25 分)
    1055 The World's Richest (25 分)
  • 原文地址:https://www.cnblogs.com/firstcsharp/p/4127898.html
Copyright © 2011-2022 走看看