zoukankan      html  css  js  c++  java
  • MVC5+EF+AutoFac+AutoMapper轻型架构

    今天和大家一起学习一下当前流行的MVC5+EF+AutoFac+AutoMapper轻型架构,先上一张框架图

    一、项目基本框架搭建

    写程序的顺序是Model-DAL-BLL-UI,Model层就是表实体,我们略过,下面上DAL层代码

    using Model;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Linq.Expressions;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace DAL
    {
        public class BaseDal<T> where T : class, new()
        {
            public DataModel _currentDbContext = DbContextFactory.GetDbContext();
    
            public T Add(T item)
            {
                return _currentDbContext.Set<T>().Add(item);
            }
    
            public int Count(Expression<Func<T, bool>> predicate)
            {
                //set<t>针对对上下文和基础存储中给定类型的实体的访问返回一个 DbSet<TEntity> 实例。
                return _currentDbContext.Set<T>().Count(predicate);//返回指定序列中满足条件的元素数量。 
            }
    
            public bool Update(T entity)
            {
                //Attach将实体以“未更改”的状态放置到上下文中,就好像从数据库读取了该实体一样。
                _currentDbContext.Set<T>().Attach(entity);
                _currentDbContext.Entry<T>(entity).State = System.Data.Entity.EntityState.Modified;
                return _currentDbContext.SaveChanges() > 0;
            }
    
            public bool Delete(T entity)
            {
                _currentDbContext.Set<T>().Attach(entity);
                _currentDbContext.Entry<T>(entity).State = System.Data.Entity.EntityState.Deleted;
                return _currentDbContext.SaveChanges() > 0;
            }
    
            public bool Exist(Expression<Func<T, bool>> anyLambda)
            {
                return _currentDbContext.Set<T>().Any(anyLambda);
            }
    
            public T Find(Expression<Func<T, bool>> whereLambda)
            {
                T entity = _currentDbContext.Set<T>().FirstOrDefault();
                return entity;
            }
    
            public IQueryable<T> FindList(Expression<Func<T, bool>> whereLamdba, string orderName, bool isAsc)
            {
                var _list = _currentDbContext.Set<T>().Where<T>(whereLamdba);
                _list = OrderBy(_list, orderName, isAsc);
                return _list;
            }
             
            /// <summary>
            /// 排序
            /// </summary>
            /// <typeparam name="T">类型</typeparam>
            /// <param name="source">原IQueryable</param>
            /// <param name="propertyName">排序属性名</param>
            /// <param name="isAsc">是否正序</param>
            /// <returns>排序后的IQueryable<T></returns>
            private IQueryable<T> OrderBy(IQueryable<T> source, string propertyName, bool isAsc)
            {
                if (source == null) throw new ArgumentNullException("source", "不能为空");
                if (string.IsNullOrEmpty(propertyName)) return source;
                var _parameter = Expression.Parameter(source.ElementType);
                var _property = Expression.Property(_parameter, propertyName);
                if (_property == null) throw new ArgumentNullException("propertyName", "属性不存在");
                var _lambda = Expression.Lambda(_property, _parameter);
                var _methodName = isAsc ? "OrderBy" : "OrderByDescending";
                var _resultExpression = Expression.Call(typeof(Queryable), _methodName, new Type[] { source.ElementType, _property.Type }, source.Expression, Expression.Quote(_lambda));
                return source.Provider.CreateQuery<T>(_resultExpression);
            }
    
    
            public IQueryable<T> FindPageList(int pageIndex, int pageSize, out int totalRecord, Expression<Func<T, bool>> whereLamdba, string orderName, bool isAsc)
            {
                var _list = _currentDbContext.Set<T>().Where<T>(whereLamdba);
                totalRecord = _list.Count();
                //if (isAsc) _list = _list.OrderBy<T, S>(orderLamdba).Skip<T>((pageIndex - 1) * pageSize).Take<T>(pageSize);
                //else _list = _list.OrderByDescending<T, S>(orderLamdba).Skip<T>((pageIndex - 1) * pageSize).Take<T>(pageSize);
                _list = OrderBy(_list, orderName, isAsc).Skip<T>((pageIndex - 1) * pageSize).Take<T>(pageSize);
                return _list;
            }
    
        }
    }
    BaseDal

    相信大家都能看懂吧,EF框架抽象出来的CRUD方法

    namespace DAL
    {
        public class UserInfoDal:BaseDal<UserInfo>,IUserInfoDal
        {      
        }
    }
    UserInfoDal

    IDAL层代码给大家看一下,因为我们要解耦各个层之间的首先要实现面向接口编程

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Linq.Expressions;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace IDAL
    {
        public interface IBaseDal<T>
        {
            T Add(T item);
            int Count(Expression<Func<T, bool>> predicate);
            bool Update(T entity);
            bool Delete(T entity);
            bool Exist(Expression<Func<T, bool>> anyLambda);
            T Find(Expression<Func<T, bool>> whereLambda);
            IQueryable<T> FindList(Expression<Func<T, bool>> whereLamdba, string orderName, bool isAsc);
            IQueryable<T> FindPageList(int pageIndex, int pageSize, out int totalRecord, Expression<Func<T, bool>> whereLamdba, string orderName, bool isAsc);
        }
    }
    IBaseDal

    BLL层的代码大家都能看懂吧,看不懂的话要多加研究了

    using DAL;
    using IDAL;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Linq.Expressions;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace BLL
    {
        public class BaseService<T> where T:class,new()
        {
            public BaseService(IBaseDal<T> currentDal)
            {
                this._currentDal = currentDal;
            }
            protected IBaseDal<T> _currentDal { get; set; }
            public T Add(T item)
            {
                return _currentDal.Add(item);
            }
    
           
            public int Count(Expression<Func<T, bool>> predicate)
            {
                return _currentDal.Count(predicate);
            }
    
            public bool Update(T entity)
            {
                return _currentDal.Update(entity);
            }
    
            public bool Delete(T entity)
            {
                return _currentDal.Delete(entity);
            }
    
            public bool Exist(Expression<Func<T, bool>> anyLambda)
            {
                return _currentDal.Exist(anyLambda);
            }
    
            public T Find(Expression<Func<T, bool>> whereLambda)
            {
                return _currentDal.Find(whereLambda);
            }
    
            public IQueryable<T> FindList(Expression<Func<T, bool>> whereLamdba, string orderName, bool isAsc)
            {
                return _currentDal.FindList(whereLamdba, orderName, isAsc);
            }
            
            public IQueryable<T> FindPageList(int pageIndex, int pageSize, out int totalRecord, Expression<Func<T, bool>> whereLamdba, string orderName, bool isAsc)
            {
                return _currentDal.FindPageList(pageIndex, pageSize, out totalRecord, whereLamdba, orderName, isAsc);
            }
        }
    }
    BaseService

    同样面向接口编程,我们也要抽象出IBLL层,实现与UI的面向接口

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Linq.Expressions;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace IBLL
    {
        public interface IBaseService<T> where T:class,new()
        {
            T Add(T item);
    
            int Count(Expression<Func<T, bool>> predicate);
    
            bool Update(T entity);
    
            bool Delete(T entity);
    
            bool Exist(Expression<Func<T, bool>> anyLambda);
    
            T Find(Expression<Func<T, bool>> whereLambda);
    
            IQueryable<T> FindList(Expression<Func<T, bool>> whereLamdba, string orderName, bool isAsc);
    
            IQueryable<T> FindPageList(int pageIndex, int pageSize, out int totalRecord, Expression<Func<T, bool>> whereLamdba, string orderName, bool isAsc);
            
        }
    }
    IBaseService

    二、运用AutoFac进行依赖注入,实现各层次间低耦合。(其实就是一个第三方的抽象工厂,我们自己也是可以写出来的,相信自己)

    autofac 4.0 版本以上,官方建议使用外代*.JSON\*.XML的文件进行注入,而不是直接写在web.config文件中(如我们的架构图)

    接下来看一下,如何运用Autofac进行依赖注入,先介绍代码自动注入

    //创建autofac管理注册类的容器实例
                ContainerBuilder builder = new ContainerBuilder();
    
                #region 全自动api注入
                //UI项目只用引用service和repository的接口,不用引用实现的dll。
    
                //如需加载实现的程序集,将dll拷贝到bin目录下即可,不用引用dll
    
                var IServices = Assembly.Load("IBLL");
                var Services = Assembly.Load("BLL");
                var IRepository = Assembly.Load("IDAL");
                var Repository = Assembly.Load("DAL");
    
                //根据名称约定(数据访问层的接口和实现均以Repository结尾),实现数据访问接口和数据访问实现的依赖
                builder.RegisterAssemblyTypes(IRepository, Repository)
                 .Where(t => t.Name.EndsWith("Dal"))
                 .AsImplementedInterfaces();
    
                //根据名称约定(服务层的接口和实现均以Service结尾),实现服务接口和服务实现的依赖
                builder.RegisterAssemblyTypes(IServices, Services)
                  .Where(t => t.Name.EndsWith("Service"))
                  .AsImplementedInterfaces();
    
                #endregion

    下面是配置文件注入,这种配置文件注入适合大项目,管理方便

    {
      "components": [
        {
          "type": "DAL.UserInfoDal,DAL",
          "services": [
            {
              "type": "IDAL.IUserInfoDal"
            }
          ],
          "injectProperties": true
        },
        {
          "type": "DAL.OrderInfoDal,DAL",
          "services": [
            {
              "type": "IDAL.IOrderInfoDal"
            }
          ],
          "injectProperties": true
        },
        {
          "type": "BLL.UserInfoService,BLL",
          "services": [
            {
              "type": "IBLL.IUserInfoService"
            }
          ],
          "injectProperties": true
        },
        {
          "type": "BLL.OrderInfoService,BLL",
          "services": [
            {
              "type": "IBLL.IOrderInfoService"
            }
          ],
          "injectProperties": true
        }
      ]
    
    }
    json文件代码

    配置方式注入代码如下:

               #region 配置注入适合大项目
    
                var config = new ConfigurationBuilder();
                //config.AddXmlFile(@"D:\ASP.NET成長之路\asp.net经典框架网络资源\AutoFac\AutoFacDemo\AutoFacDemo\IOC\auto.xml");
                config.AddJsonFile(@"D:\ASP.NET成長之路\asp.net经典框架网络资源\AutoFac\AutoFacDemo\AutoFacDemo\IOC\auto.json");
                var module = new ConfigurationModule(config.Build());
    
                #endregion

    不管用什么样的方式注入,最后要和MVC融合使用的话必选加载下面的代码:

    //使用Autofac提供的RegisterControllers扩展方法来对程序集中所有的Controller一次性的完成注册
                builder.RegisterControllers(Assembly.GetExecutingAssembly()).PropertiesAutowired();//生成具体的实例(属性注入)
                var container = builder.Build();
                //下面就是使用MVC的扩展 更改了MVC中的注入方式.
                DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

    并且要在Global文件中的Application_Start()执行注入的方法(将上面的注入代码封装到一个类的方法中)

    public class MvcApplication : System.Web.HttpApplication
        {
            protected void Application_Start()
            {
                //autofac注入
                AutoFacInitialize.AutofacIntitialy();
    
                Database.SetInitializer(new UseInfoInitializer());
                AreaRegistration.RegisterAllAreas();
                RouteConfig.RegisterRoutes(RouteTable.Routes);
            }
        }

    今天先写到这里吧,明天或者后天,把AutoMapper的融入写出来。

    各位园友,多多指教,小僧可能有些地方有缺陷,多多留言,共同进步,谢谢!

  • 相关阅读:
    linux下&quot;=&quot;号与&quot;==&quot;号
    设单链表中存放n个字符,试设计一个算法,使用栈推断该字符串是否中心对称
    Android系统开发(2)——GDB调试工具
    JavaScript、jQuery、HTML5、Node.js实例大全-读书笔记4
    我的编程之路(十八) 团队开发
    C语言中的函数指针
    BeagleBone Black 板第三课:Debian7.5系统安装和远程控制BBB板
    爱尔威火星车 AirWheel 电动独轮车
    祖国版SoloWheel:Airwheel爱尔威火星车 拆箱&上手经验_运动户外_晒物广场_什么值得买
    打工女孩 (豆瓣)
  • 原文地址:https://www.cnblogs.com/xqdotnet/p/6682289.html
Copyright © 2011-2022 走看看