1. 程式人生 > >ioc初步理解(二) 簡單實用autofac搭建mvc三層+automapper=》ioc(codeFirst)

ioc初步理解(二) 簡單實用autofac搭建mvc三層+automapper=》ioc(codeFirst)

深入 prop 做了 初始 turn build asa change work

   之前在園子閑逛的時候,發現許多關於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:\Users\Fates\source\repos\automapperTS\autoTS.Mapperx\EntityExtMethod.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下載地址。同時也希望各位大牛的的意見與指點。

ioc初步理解(二) 簡單實用autofac搭建mvc三層+automapper=》ioc(codeFirst)