• ioc初步理解(二) 简单实用autofac搭建mvc三层+automapper=》ioc(codeFirst)


       之前在园子闲逛的时候,发现许多关于automapper的文章,以及用aotufac+automapper合在一起用。当然发现大多数文章是将automapper的特点说出或将automapper几处关键代码放出。当然有过基础的人看这种文章没有什么问题,但是对于完全没有基础的小白来看完全是灾难级别的(我就是),经常按着博文一点一点的写,突然发现少了一部分导致代码无法运行。在搜索各种文章之后,终于用自己的理解写出了一个简单的运用automapper的demo,日后待我对automapper理解加深会进一步更新。【此文章希望对想能初步运用automapper的小白写出。当然也希望各位大牛提出意见】(关于autofac详细讲解)

    0】首先看看automapper的介绍吧:

    automapper是对象到对象的映射工具。在完成映射规则之后,automapper可以将源对象转换为目标对象。

    1】首先放出项目结构图

    由于此demo运用的是mvc三层+autofac实现依赖注入,所以文件中有三层以及ui层app_Start下的autoFacConfig.cs文件。之前有一篇博文详细讲解了autofac,所以这里只是简单介绍一下代码。主要目光放在mode层和automapper相关的文件。

    2】首先贴出各层代码

    model文件下结构

    可以看到model文件夹下有两个内库autoTS.Model和autoTS.ModelView(其实autoTS.ModelView下文件可以放到autoTS.Model中,刚刚写的时候忘记了)

    autoTS.Mode中system文件夹中文件是和数据库中表一一对应。而autoTS.ModelView下system中文件则是和autoTS.Mode中system文件夹中文件对应(为了实现automapper的功能)将两者进行对比一下

    可以看到两者的不同,明显负责连接数据库的model彼modelView多了一些标志(上传csdn中代码的时候忘记写这些,可以下载demo和阅读此博客)

    然后autoTs.model层下DBContext.cs代码(autoTS.Model层需要在nuget中引用EntityFramework)

       public class DBContext : DbContext
        {
    
            public DBContext() : base("name=DatabaseTS") { }//配置文件中连接数据库设置的name
            public DbSet<User> User { get; set; }
    
            public DbSet<UserType> UserType { get; set; }
        }
    View Code

    3】接下来是DAL文件的结构以及代码(不是本文章主要内容值贴出代码,不加以详细说明)

    先是idal层中的文件代码(需要nuget中引用EntityFramework 和autoTS.Model)

    IBaseDal.cs

      //具体业务依赖于接口
        public interface IBaseDal<TEntity> where TEntity : class
        {
            #region 1.0 增
    
            void Add(TEntity model);
    
            #endregion
    
            #region 2.0 删
    
            void Delete(TEntity model, bool isAddedDbContext);
    
    
    
            #endregion
    
            #region 3.0 改
    
    
            void Edit(TEntity model, string[] propertyNames);
    
    
            #endregion
    
            #region 4.0 查
    
            #region 4.0.1 根据条件查询
    
    
            List<TEntity> QueryWhere(Expression<Func<TEntity, bool>> where);
    
            #endregion
            #endregion
    
            #region 5.0 统一保存
    
            /// <summary>
            /// 统一将EF容器对象中的所有代理类生成相应的sql语句发给db服务器执行
            /// </summary>
            /// <returns></returns>
            int SaveChanges();
    
            #endregion
    
        }
    View Code

    system中User_IDAL.cs

        public interface User_IDAL : IBaseDal<User>
        {
        }
    View Code

    然后是dal层中的代码(需要引用EntityFramework 和autoTS.Model、autoTS.IDAL)

    BaseDal.cs

        public class BaseDal<TEntity> : IBaseDal<TEntity> where TEntity : class
        {
            //1.0  实例化EF上下文 
            DbContext db = BaseDBContent.GetCurrentThreadInstance();
    
            //2.0 定义DbSet<T> 对象
            public DbSet<TEntity> _dbset;
    
            //3.0 在构造函数的初始化_dbset
            public BaseDal()
            {
                _dbset = db.Set<TEntity>();
            }
    
    
            #region 1.0 增
    
            public virtual void Add(TEntity model)
            {
                //1.0 参数合法性验证
                if (model == null)
                {
                    throw new Exception("BaseRepository泛型类中,新增操作的实体不能为空");
                }
    
    
                //2.0 进行新增操作 
                _dbset.Add(model);
            }
    
    
            #endregion
    
            #region 2.0 删
    
            public virtual void Delete(TEntity model, bool isAddedDbContext)
            {
                //1.0 参数合法性验证
                if (model == null)
                {
                    throw new Exception("BaseRepository泛型类中,删除操作的实体不能为空");
                }
    
                //2.0 进行删除逻辑处理
                if (!isAddedDbContext)
                {
                    _dbset.Attach(model);
                }
    
                _dbset.Remove(model);
            }
    
    
            #endregion
    
            #region 3.0 改
    
            /// <summary>
            /// 编辑,约定model 是一个自定义的实体,没有追加到EF容器中的
            /// </summary>
            /// <param name="model"></param>
            public virtual void Edit(TEntity model, string[] propertyNames)
            {
                //0.0 关闭EF的实体属性合法性检查
                db.Configuration.ValidateOnSaveEnabled = false;
    
                //1.0 参数合法性验证
                if (model == null)
                {
                    throw new Exception("BaseRepository泛型类中,编辑操作的实体不能为空");
                }
    
                if (propertyNames == null || propertyNames.Length == 0)
                {
                    throw new Exception("BaseRepository泛型类中,编辑操作的属性数组必须至少有一个值");
                }
    
                //2.0 将model追加到EF容器中的
                DbEntityEntry entry = db.Entry(model);
                entry.State = EntityState.Unchanged;
    
                foreach (var item in propertyNames)
                {
                    entry.Property(item).IsModified = true;
                }
            }
    
            #endregion
    
            #region 4.0 查
    
    
    
            /// <summary>
            /// 带条件查询
            /// </summary>
            /// <param name="where"></param>
            /// <returns></returns>
            public virtual List<TEntity> QueryWhere(Expression<Func<TEntity, bool>> where)
            {
                return _dbset.Where(where).ToList();
            }
            #endregion
    
    
            #region 5.0 统一保存
    
            /// <summary>
            /// 统一将EF容器对象中的所有代理类生成相应的sql语句发给db服务器执行
            /// </summary>
            /// <returns></returns>
            public virtual int SaveChanges()
            {
                try
                {
                    return db.SaveChanges();
                }
                catch (Exception ex)
                {
                    throw ex;
                }
            }
    
            #endregion
    
    
        }
    View Code

    BaseDBContent.cs

       public class BaseDBContent 
        {
            
            //获取当前EF上下文的唯一实例
            public static DbContext GetCurrentThreadInstance()
            {
                DbContext obj = CallContext.GetData(typeof(BaseDBContent).FullName) as DbContext;
                if (obj == null)
                {
                    obj = new DBContext();
                    CallContext.SetData(typeof(BaseDBContent).FullName, obj);
                }
                return obj;
            }
        }
    View Code

    system中User_DAL.cs

        public class User_DAL : BaseDal<User>, User_IDAL
        {
        }
    View Code

    4】bll文件中代码和结构

    ibll层代码(此层需要引用autoTS.Model)

    IBaseBLL.cs

     public interface IBaseBLL<TEntity> where TEntity : class
        {
            #region 1.0 增
    
            void Add(TEntity model);
    
            #endregion
    
            #region 2.0 删
    
            void Delete(TEntity model, bool isAddedDbContext);
    
    
    
            #endregion
    
            #region 3.0 改
    
            /// <summary>
            /// 编辑,约定model 是一个自定义的实体,没有追加到EF容器中的
            /// </summary>
            /// <param name="model"></param>
            void Edit(TEntity model, string[] propertyNames);
    
    
            #endregion
    
            #region 4.0 查
    
    
    
            /// <summary>
            /// 带条件查询
            /// </summary>
            /// <param name="where"></param>
            /// <returns></returns>
            List<TEntity> QueryWhere(Expression<Func<TEntity, bool>> where);
    
    
    
    
    
            #endregion
    
    
            #region 5.0 统一保存
    
            /// <summary>
            /// 统一将EF容器对象中的所有代理类生成相应的sql语句发给db服务器执行
            /// </summary>
            /// <returns></returns>
            int SaveChanges();
    
            #endregion
    
    
        }
    View Code

    system文件夹下User_IBLL.cs

     public interface User_IBLL : IBaseBLL<User>
        {
        }
    View Code

    bll层中代码(需要引用autoTS.Model、autoTS.IBLL、autoTS.IDAL)

    BaseBLL.cs

      public class BaseBLL<TEntity> : IBaseBLL<TEntity> where TEntity : class
        {
            protected IBaseDal<TEntity> dal = null;
            #region 1.0 增
    
            public virtual void Add(TEntity model)
            {
                dal.Add(model);
            }
    
    
            #endregion
    
            #region 2.0 删
    
            public virtual void Delete(TEntity model, bool isAddedDbContext)
            {
                dal.Delete(model, isAddedDbContext);
            }
    
    
            #endregion
    
            #region 3.0 改
    
            /// <summary>
            /// 编辑,约定model 是一个自定义的实体,没有追加到EF容器中的
            /// </summary>
            /// <param name="model"></param>
            public virtual void Edit(TEntity model, string[] propertyNames)
            {
                dal.Edit(model, propertyNames);
            }
    
            #endregion
    
            #region 4.0 查
    
            /// <summary>
            /// 带条件查询
            /// </summary>
            /// <param name="where"></param>
            /// <returns></returns>
            public virtual List<TEntity> QueryWhere(Expression<Func<TEntity, bool>> where)
            {
                return dal.QueryWhere(where);
            }
    
    
            #endregion
    
            #region 5.0 统一保存
    
            /// <summary>
            /// 统一将EF容器对象中的所有代理类生成相应的sql语句发给db服务器执行
            /// </summary>
            /// <returns></returns>
            public virtual int SaveChanges()
            {
                return dal.SaveChanges();
            }
    
            #endregion
    
    
    
        }
    View Code

    system文件中User_BLL.cs

       public class User_BLL : BaseBLL<User>, User_IBLL
        {
            User_IDAL dalSer;
            public User_BLL(User_IDAL dalSer)
            {
                base.dal = dalSer;
                this.dalSer = dalSer;
            }
        }
    View Code

     5】公共层all文件夹代码以及结构(圈起来的都是要引用的,前面有红线的则是在nuget中引用  注意引用mvc的版本必须和自己ui层mvc版本一致)

    IOCDI.CS

    using autoTS.IBLL.system;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Web.Mvc;
    
    namespace autoTS.Mapperx.System
    {
        public   class IOCDI : Controller
        {
            protected User_IBLL UserSer;
            protected UserType_IBLL UserTypeSer;
        }
    }
    View Code

    (本次重点)EntityExtMethod.cs中代码是为了实现automapper

    using AutoMapper;
    using autoTS.Model.System;
    using autoTS.ModelView.SystemView;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace autoTS.Mapperx
    {
        public static class EntityExtMethod
        {
     
         
    
    
            #region UserView-User
            public static UserView EntityMap(this User model)
            {
                //利用AutoMapper 来将 User 的属性值动态拷贝到 UserView 类中对应的同名属性值中
                // 开始转换
                return Mapper.Map<User, UserView>(model);
            }
            public static User  EntityMap(this UserView model)
            {
                //利用AutoMapper 来将 UserView 的属性值动态拷贝到 User 类中对应的同名属性值中
                // 开始转换
                return Mapper.Map<UserView, User>(model);
            }
            #endregion
            #region UserTypeView-Type
            public static UserTypeView EntityMap(this UserType model)
            {
                //利用AutoMapper 来将 UserType 的属性值动态拷贝到 UserTypeView 类中对应的同名属性值中
                // 开始转换
                return Mapper.Map<UserType, UserTypeView>(model);
            }
            public static UserType EntityMap(this UserTypeView model)
            {
                //利用AutoMapper 来将 UserTypeView 的属性值动态拷贝到 UserType 类中对应的同名属性
                // 开始转换
                return Mapper.Map<UserTypeView, UserType>(model);
            }
            #endregion
        }
    }
    View Code

    6】最后来到ui层

     方框里面是引用部分。而前面带红线的则是需要到nuget中引用(注意第二个autofac.integration.MVC是在nuegt中引用autofac.MVC5得到)

    首先在app_Start中添加AutoFacConfig.cs(关于这部分内容,之前一份博客已经讲过就不多重复)

    using Autofac;
    using Autofac.Integration.Mvc;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Reflection;
    using System.Web;
    using System.Web.Mvc;
    
    namespace WebApplication1.App_Start
    {
        public class AutoFacConfig
        { /// <summary>
          /// 负责调用autofac框架实现业务逻辑层和数据仓储层程序集中的类型对象的创建
          /// 负责创建MVC控制器类的对象(调用控制器中的有参构造函数),接管DefaultControllerFactory的工作
          /// </summary>
            public static void Register()
            {
                //实例化一个autofac的创建容器
                var builder = new ContainerBuilder();
                //告诉Autofac框架,将来要创建的控制器类存放在哪个程序集 (IOCtsX.UI)
                Assembly controllerAss = Assembly.Load("WebApplication1");
                builder.RegisterControllers(controllerAss);
    
                //告诉autofac框架注册数据仓储层所在程序集中的所有类的对象实例
                Assembly respAss = Assembly.Load("autoTS.DAL");
                //创建respAss中的所有类的instance以此类的实现接口存储
                builder.RegisterTypes(respAss.GetTypes()).AsImplementedInterfaces();
    
                //告诉autofac框架注册业务逻辑层所在程序集中的所有类的对象实例
                Assembly serpAss = Assembly.Load("autoTS.BLL");
                //创建serAss中的所有类的instance以此类的实现接口存储
                builder.RegisterTypes(serpAss.GetTypes()).AsImplementedInterfaces();
    
                //创建一个Autofac的容器
                var container = builder.Build();
                //将MVC的控制器对象实例 交由autofac来创建
                DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
    
    
            }
        }
    }
    View Code

    然后再app_Start中添加AutoMapperConfig.cs。这部分一看就是为了实现automapper内容

    using AutoMapper;
    using autoTS.Model.System;
    using autoTS.ModelView.SystemView;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    
    namespace WebApplication1.App_Start
    {
        public class AutoMapperConfig
        {
            public static void Initializex()
            {
                //Entity与DTO的映射 初始化映射的方向 (注册)  写在这里是因为只需要注册一次, 
                //放在C:UsersFatessource
    eposautomapperTSautoTS.MapperxEntityExtMethod.cs 中因为每次使用都会注册从而报错(只需要注册一次)
                Mapper.Initialize(x =>
                {
                    x.CreateMap<User, UserView>(); //创建User映射到UserView
                    x.CreateMap<UserView, UserType>(); //反之
                    x.CreateMap<UserType, UserTypeView>(); //创建UserType映射到UserTypeView
                    x.CreateMap<UserTypeView, UserType>(); //反之
                }); 
            }
        }
    }
    View Code

    注意自己引用的automapper,高版本和低版本的写法有些不同,如图

     如果不知道自己引用的是低版本还是高版本的话,就写Mapper.CreateMap<user, userView>();看是否报错,如果报错则是高版本的automapper,使用左上图写法,否者用右上图写法。

    写完这些文件之后去Global.asax中进行注册

    最后,我们来到控制器,写一个demo

    最后来数据库看看结构

     【总结】由于博主技术渣渣,所以文章内容不是太深入。只是简单介绍了如何简单的使用automapper,日后待到这一块深入了解之后,必将更新。此文章适合需要入门automapper的小白,跟着文章一步一步走必将写出一个可运行的demo。因为项目的所有代码和引用文件都已经做了详细的说明。如果懒人党的话,稍后会更新demo下载地址。同时也希望各位大牛的的意见与指点。

  • 相关阅读:
    nginx 配置文件详解
    nginx的location匹配规则
    mysql常用函数
    jquery封装的ajax请求
    docker
    in与exists和not in 与 not exists的区别
    mysql授权
    线程池
    springboot+rediscluster
    常用网址
  • 原文地址:https://www.cnblogs.com/1439107348s/p/9967935.html
Copyright © 2020-2023  润新知