MVC5+EF+AutoFac+AutoMapper轻型架构
Posted Constructor
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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; } } }
相信大家都能看懂吧,EF框架抽象出来的CRUD方法
namespace DAL { public class UserInfoDal:BaseDal<UserInfo>,IUserInfoDal { } }
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); } }
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); } } }
同样面向接口编程,我们也要抽象出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); } }
二、运用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 } ] }
配置方式注入代码如下:
#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的融入写出来。
各位园友,多多指教,小僧可能有些地方有缺陷,多多留言,共同进步,谢谢!
以上是关于MVC5+EF+AutoFac+AutoMapper轻型架构的主要内容,如果未能解决你的问题,请参考以下文章
一步一步创建ASP.NET MVC5程序[Repository+Autofac+Automapper+SqlSugar]
一步一步创建ASP.NET MVC5程序[Repository+Autofac+Automapper+SqlSugar]