ioc初步理解(一) 簡單實用autofac搭建mvc三層+ioc(codeFirst)


1】首先搭好框架

 1.1】搭建ui層

  1.2】創建其他內庫文件

整個項目基本部分搭建完畢之后如下

2】使用nuget引用文件

先在每一個項目中引入ef

然后再UI層引入以下兩個文件autofac和Autofac.Mvc5

 

 

3】因為本demo實用codefirst,所以先去model層完善

  3.1】創建幾個model 

   創建一個  User.cs。里面放幾個屬性 id、name、pwd。

  3.2】創建DBContext.cs這個文件的作用是自動生成數據庫 內容如下

 

  3.3】創建DbModelContextFactory.cs。此處作用是:獲取當前EF上下文的唯一實例;  內容如下

4】創建DAL層內容【需要使用nuget引入ef文件  和model文件。dal層還需要引入idal】

  4.1】首先完善IDAL(接口)內容

    4.1.1】首先完成基礎部分,創建IBaseDAL.cs 在里面添加增刪改查這四個基本操作(注意IDAL中全是接口不是類,所以新建的時候注意吧class改成interface)代碼如下
 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

 

    4.1.2】根據自己在model中創建的模型,在此處也一一對應的創建其dal層接口。所在這里創建一個IUser_DAL.cs  內容如下:

因為所創建的model只有一個user,所以IDAL層到此結束。

  4.2】接下來創建DAL部分內容

   4.2.1】首先創建DbContextFactory.cs  =>   //獲取當前EF上下文的唯一實例 代碼如下

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

 

    4.2.2】首先創建BaseDAL.cs 在里面寫入具體的增刪該查操作,代碼如下:
public class BaseDAL<TEntity> : IBaseDAL<TEntity> where TEntity : class
    {//1.0  實例化EF上下文 
        DbContext db = DbContextFactory.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
   4.2.3】創建 User_DAL.cs文件,內容如下

 

5】創建BLL的內容【需要使用nuget引入ef文件   和導入model層。dal層文件,bll層還需要引入ibll層】

  5.1】先創建IBLL(接口)層的內容

    5.1.1】創建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
   5.1.2】根據model層的模型創建ibll層接口。所在這里創建一個IUser_BLL.cs  內容如下:

 

  5.2】完善BLL層內容

    5.2.1】創建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
   5.2.2】根據model層的模型創建bll層文件。所在這里創建一個User_BLL.cs  代碼如下:
   public class User_BLL : BaseBLL<User>, IUser_BLL
    {
        IUser_DAL dalSer;
        public User_BLL(IUser_DAL dalSer)
        {
            base.dal = dalSer;
            this.dalSer = dalSer;
        }
    }
View Code

至此,基礎部分建立完畢,接下來建立ui層內容

6】建立UI層內容【需要引入bll文件和dal文件  也就是6.1中圖中的兩個文件,否則autofac報錯,找到不到文件】

  6.1】首先在App_Start文件夾下建AutoFacConfig.cs文件

 

代碼:

public class AutoFacConfig
    { /// <summary>
      /// 負責調用autofac框架實現業務邏輯層和數據倉儲層程序集中的類型對象的創建
      /// 負責創建MVC控制器類的對象(調用控制器中的有參構造函數),接管DefaultControllerFactory的工作
      /// </summary>
        public static void Register()
        {
            //實例化一個autofac的創建容器
            var builder = new ContainerBuilder();
            //告訴Autofac框架,將來要創建的控制器類存放在哪個程序集 (IOCtsX.UI)
            Assembly controllerAss = Assembly.Load("IOCtsX.UI");
            builder.RegisterControllers(controllerAss);

            //告訴autofac框架注冊數據倉儲層所在程序集中的所有類的對象實例
            Assembly respAss = Assembly.Load("IOCtsX.DAL");
            //創建respAss中的所有類的instance以此類的實現接口存儲
            builder.RegisterTypes(respAss.GetTypes()).AsImplementedInterfaces();

            //告訴autofac框架注冊業務邏輯層所在程序集中的所有類的對象實例
            Assembly serpAss = Assembly.Load("IOCtsX.BLL");
            //創建serAss中的所有類的instance以此類的實現接口存儲
            builder.RegisterTypes(serpAss.GetTypes()).AsImplementedInterfaces();

            //創建一個Autofac的容器
            var container = builder.Build();
            //將MVC的控制器對象實例 交由autofac來創建
            DependencyResolver.SetResolver(new AutofacDependencyResolver(container));


        }
    }
View Code

 

  6.2】然后再Global.asax中進行配置 如下:

  6.3】創建一個公共層,使用nuget引入mvc和ef。添加文件IOCDI.cs 根據創建mode層中模型的數量寫入內容:(寫公共層主要考慮項目的擴展性,如果本項目中需要些api或者其他ui層時候,避免代碼重復)【需要用nuget引入mvc、ef 和ibll層(注意此處mvc版本必須和ui層中mvc版本相同)】

 

7】最后創建一個控制器添加數據看看,

 7.1】先配置Web.config

 

 7.2】創建一個測試控制器(由於是codefirs所以不需要先創建數據庫)

最后查看數據庫

 

 

【最后附上關於autofac的幾點疑惑】

1因為在ui層的App_Start下的AutoFacConfig.cs需要,所以ui層必須引用bll層和dal層,這和三層的理念有些差異。因為三層中ui層並不需要引入dal層。

【結尾說明,關於了解autofac花掉的時間說長也長說短也短。原本以為在博客園、csdn上面找一找就能馬上得到一個可以運行的demo,但是很多博主都是按照自己的理解去寫,在博文中或多或少會掉一些內容,這些內容對於博主和一些大牛來說是可以忽略不計的,因此博文只需要核心代碼就可以,但是對於我這種萌新來說簡直是災難級別的,因為跟着博主敲打代碼過程中時長因為缺點什么而無法運行,自己也不知道錯誤在哪。因此不得不敲到一半立馬換下一個。導致效率低下。所以在寫這個博文的過程中。我盡量將每一個細節全部羅列出來,以免像我這樣的小白看不懂。照着這個流程講代碼敲出來並且運行時沒什么大問題的。因為我每敲完一處就寫一點。最后將代碼運行完畢,才敢上傳。如果各位看官覺得有什么問題可以在下方留言】

【如果需要代碼可以去此下載,當然懶人也需要一點付出(csdn 3積分)。博主希望大家盡量多動手,多理解。不要像我之前一樣只需要demo從不看文章導致后來吃了許多虧】

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM