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();
  • 相关阅读:
    EF Core 执行SQL语句和存储过程
    SQL优化之SELECT COUNT(*)
    SQL优化之SQL 进阶技巧(下)
    SQL优化之SQL 进阶技巧(上)
    旅游攻略:重庆红色之旅
    ASP.NET Core在CentOS上的最小化部署实践
    Windows平台部署Asp.Net Core应用
    kali 免杀工具shellter安装以及使用
    Ubuntu Server18.04配置静态IP
    Centos7系统配置静态IP
  • 原文地址:https://www.cnblogs.com/firstcsharp/p/4127898.html
Copyright © 2011-2022 走看看