第十節:基於MVC5+Unity+EF+Log4Net的基礎結構搭建

一. 前言html

  本節繼續探討一種新的框架搭建模式,框架的結構劃分和上一節是相同的,本節IOC框架換成了Unity,而且採用構造函數注入的方式,另外服務層的封裝模式也發生了變化,下面將詳細的進行探討。
(一). 技術選型

  1. DotNet框架:4.6sql

  2. 數據庫訪問:EF 6.2 (CodeFrist模式)數據庫

  3. IOC框架:Unity 5.8.13app

  4. 日誌框架:log4net 2.0.8框架

  5. 開發工具:VS2017ide

(二). 框架目標

  1. 一個項目同時鏈接多個相同種類的數據庫,在一個方法中能夠同時對多個數據進行操做。函數

  2. 支持多種數據庫:SqlServer、MySQL、Oracle,靈活的切換數據庫。工具

  3. 抽象成支持多種數據庫鏈接方式:EF、ADO.Net、Dapper。佈局

 

二. 搭建思路開發工具

1. 層次劃分

  將框架分爲:Ypf.Data、Ypf.IService、Ypf.Service、Ypf.DTO、Ypf.Utils、Ypf.AdminWeb 六個基本層(後續還會補充 Ypf.Api層),每層的做用分別爲:

  ①. Ypf.Data:存放鏈接數據庫的相關類,包括EF上下文類、映射的實體類、實體類的FluentApi模式的配置類。

  ②. Ypf.IService:業務接口層,用來約束接口規範。

  ③. Ypf.Service:業務層,用來編寫整套項目的業務方法,但須要符合Ypf.IService層的接口約束。

  ④. Ypf.DTO: 存放項目中用到的自定義的實體類。

  ⑤. Ypf.Utils: 工具類

  ⑥. Ypf.AdminWeb: 表現層,系統的展現、接受用戶的交互,傳遞數據,業務對接。

PS:後續會補充Ypf.Api層,用於接受移動端、或其餘客戶端接口數據,進行相應的業務對接處理。

2. Ypf.Data層的剖析

  EF封裝到【Ypf.Data】層,經過Nuget引入EF的程序集,利用【來自數據庫的code first】的模式先進行映射,後續經過DataAnnotations FluentAPI混合使用。該層結構以下:

PS:EF的關閉默認策略、EF的DataAnnotations、EF的FluentAPI模式, 在關閉數據庫策略的狀況下,不管哪一種模式都須要顯式的 ToTable來映射表名,不然會提示該類找不到。

EF配置詳情參考:

         第十五節: EF的CodeFirst模式經過DataAnnotations修改默認協定

         第十六節: EF的CodeFirst模式經過Fluent API修改默認協定

給【Ypf.AdminWeb】層,經過Nuget引入EF的程序集,並配置數據庫鏈接字符串,直接在該層測試數據庫訪問。【測試經過】

3. Service層和IService層簡單的封裝一下

  ①.【Ypf.Service】層只有一個BaseService普通類(非泛型)封裝,【Ypf.IService】層有設置一個IBaseService接口,BaseService類實現IBaseService接口,裏面的方法所有封裝爲泛型方法

  ②.【Ypf.Service】層中有不少自定義的 xxxService,每一個xxxService都要實現【Ypf.IService】層的IxxxService層接口,同時繼承BaseService類,這裏的xxxService層劃分並不依賴表名劃分,自定義根據業務合理起名便可。

  ③. xxxService類中,在構造函數中傳入DbContext db,但此處並不實例化,而是利用Unity進行構造函數的注入,全部的子類xxxService類中,都注入相應的EF上下文,這樣就不須要手動再傳入了(這裏須要特別注意:Unity默認支持構造函數注入,只要xxxService被配置,那麼該類中的(參數最多)的構造函數中的參數類便可以進行注入,只要在配置文件中配置上便可實現注入)。

  ④.在Unity的配置文件中進行配置IOC,在控制器中進行構造函數注入。

  ⑤ . 控制器中的Action僅僅負責傳值和簡單的一些判斷,核心業務所有都寫在Service層中。

  ⑥.  子類xxxService中的方法中,能夠直接經過 this.XXX<T>的方式調用父類BaseService中的泛型方法,db是經過子類構造函數傳到父類BaseService構造函數中。

分享BaseService類和IBaseService接口:

  1 using System;
  2 using System.Collections.Generic;
  3 using System.Data.Entity;
  4 using System.Data.SqlClient;
  5 using System.Linq;
  6 using System.Linq.Expressions;
  7 using System.Reflection;
  8 using System.Text;
  9 using System.Threading.Tasks;
 10 using Ypf.IService;
 11 
 12 namespace Ypf.Service
 13 {
 14     public class BaseService: IBaseService
 15     {
 16         /// <summary>
 17         /// 一個屬性,在該類中使用
 18         /// </summary>
 19         public DbContext db { get; private set; }
 20 
 21         /// <summary>
 22         /// 經過構造函數傳入EF的上下文
 23         /// 該上下文多是同種類型的不一樣數據庫、也多是相同結構的不一樣類型的數據庫
 24         /// 爲後面的Untiy的構造函數注入埋下伏筆
 25         /// </summary>
 26         /// <param name="db"></param>
 27         public BaseService(DbContext db)
 28         {
 29             this.db = db;
 30         }
 31 
 32 
 33         //1. 直接提交數據庫
 34 
 35         #region 01-數據源
 36         public IQueryable<T> Entities<T>() where T : class
 37         {
 38             return db.Set<T>();
 39         }
 40 
 41         #endregion
 42 
 43         #region 02-新增
 44         public int Add<T>(T model) where T : class
 45         {
 46             DbSet<T> dst = db.Set<T>();
 47             dst.Add(model);
 48             return db.SaveChanges();
 49 
 50         }
 51         #endregion
 52 
 53         #region 03-刪除(適用於先查詢後刪除 單個)
 54         /// <summary>
 55         /// 刪除(適用於先查詢後刪除的單個實體)
 56         /// </summary>
 57         /// <param name="model">須要刪除的實體</param>
 58         /// <returns></returns>
 59         public int Del<T>(T model) where T : class
 60         {
 61             db.Set<T>().Attach(model);
 62             db.Set<T>().Remove(model);
 63             return db.SaveChanges();
 64         }
 65         #endregion
 66 
 67         #region 04-根據條件刪除(支持批量刪除)
 68         /// <summary>
 69         /// 根據條件刪除(支持批量刪除)
 70         /// </summary>
 71         /// <param name="delWhere">傳入Lambda表達式(生成表達式目錄樹)</param>
 72         /// <returns></returns>
 73         public int DelBy<T>(Expression<Func<T, bool>> delWhere) where T : class
 74         {
 75             List<T> listDels = db.Set<T>().Where(delWhere).ToList();
 76             listDels.ForEach(d =>
 77             {
 78                 db.Set<T>().Attach(d);
 79                 db.Set<T>().Remove(d);
 80             });
 81             return db.SaveChanges();
 82         }
 83         #endregion
 84 
 85         #region 05-單實體修改
 86         /// <summary>
 87         /// 修改
 88         /// </summary>
 89         /// <param name="model">修改後的實體</param>
 90         /// <returns></returns>
 91         public int Modify<T>(T model) where T : class
 92         {
 93             db.Entry(model).State = EntityState.Modified;
 94             return db.SaveChanges();
 95         }
 96         #endregion
 97 
 98         #region 06-批量修改(非lambda)
 99         /// <summary>
100         /// 批量修改(非lambda)
101         /// </summary>
102         /// <param name="model">要修改實體中 修改後的屬性 </param>
103         /// <param name="whereLambda">查詢實體的條件</param>
104         /// <param name="proNames">lambda的形式表示要修改的實體屬性名</param>
105         /// <returns></returns>
106         public int ModifyBy<T>(T model, Expression<Func<T, bool>> whereLambda, params string[] proNames) where T : class
107         {
108             List<T> listModifes = db.Set<T>().Where(whereLambda).ToList();
109             Type t = typeof(T);
110             List<PropertyInfo> proInfos = t.GetProperties(BindingFlags.Instance | BindingFlags.Public).ToList();
111             Dictionary<string, PropertyInfo> dicPros = new Dictionary<string, PropertyInfo>();
112             proInfos.ForEach(p =>
113             {
114                 if (proNames.Contains(p.Name))
115                 {
116                     dicPros.Add(p.Name, p);
117                 }
118             });
119             foreach (string proName in proNames)
120             {
121                 if (dicPros.ContainsKey(proName))
122                 {
123                     PropertyInfo proInfo = dicPros[proName];
124                     object newValue = proInfo.GetValue(model, null);
125                     foreach (T m in listModifes)
126                     {
127                         proInfo.SetValue(m, newValue, null);
128                     }
129                 }
130             }
131             return db.SaveChanges();
132         }
133         #endregion
134 
135         #region 07-根據條件查詢
136         /// <summary>
137         /// 根據條件查詢
138         /// </summary>
139         /// <param name="whereLambda">查詢條件(lambda表達式的形式生成表達式目錄樹)</param>
140         /// <returns></returns>
141         public List<T> GetListBy<T>(Expression<Func<T, bool>> whereLambda) where T : class
142         {
143             return db.Set<T>().Where(whereLambda).ToList();
144         }
145         #endregion
146 
147         #region 08-根據條件排序和查詢
148         /// <summary>
149         /// 根據條件排序和查詢
150         /// </summary>
151         /// <typeparam name="Tkey">排序字段類型</typeparam>
152         /// <param name="whereLambda">查詢條件</param>
153         /// <param name="orderLambda">排序條件</param>
154         /// <param name="isAsc">升序or降序</param>
155         /// <returns></returns>
156         public List<T> GetListBy<T,Tkey>(Expression<Func<T, bool>> whereLambda, Expression<Func<T, Tkey>> orderLambda, bool isAsc = true) where T : class
157         {
158             List<T> list = null;
159             if (isAsc)
160             {
161                 list = db.Set<T>().Where(whereLambda).OrderBy(orderLambda).ToList();
162             }
163             else
164             {
165                 list = db.Set<T>().Where(whereLambda).OrderByDescending(orderLambda).ToList();
166             }
167             return list;
168         }
169         #endregion
170 
171         #region 09-分頁查詢
172         /// <summary>
173         /// 根據條件排序和查詢
174         /// </summary>
175         /// <typeparam name="Tkey">排序字段類型</typeparam>
176         /// <param name="pageIndex">頁碼</param>
177         /// <param name="pageSize">頁容量</param>
178         /// <param name="whereLambda">查詢條件</param>
179         /// <param name="orderLambda">排序條件</param>
180         /// <param name="isAsc">升序or降序</param>
181         /// <returns></returns>
182         public List<T> GetPageList<T,Tkey>(int pageIndex, int pageSize, Expression<Func<T, bool>> whereLambda, Expression<Func<T, Tkey>> orderLambda, bool isAsc = true) where T : class
183         {
184 
185             List<T> list = null;
186             if (isAsc)
187             {
188                 list = db.Set<T>().Where(whereLambda).OrderBy(orderLambda)
189                .Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();
190             }
191             else
192             {
193                 list = db.Set<T>().Where(whereLambda).OrderByDescending(orderLambda)
194               .Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();
195             }
196             return list;
197         }
198         #endregion
199 
200         #region 10-分頁查詢輸出總行數
201         /// <summary>
202         /// 根據條件排序和查詢
203         /// </summary>
204         /// <typeparam name="Tkey">排序字段類型</typeparam>
205         /// <param name="pageIndex">頁碼</param>
206         /// <param name="pageSize">頁容量</param>
207         /// <param name="whereLambda">查詢條件</param>
208         /// <param name="orderLambda">排序條件</param>
209         /// <param name="isAsc">升序or降序</param>
210         /// <returns></returns>
211         public List<T> GetPageList<T,Tkey>(int pageIndex, int pageSize, ref int rowCount, Expression<Func<T, bool>> whereLambda, Expression<Func<T, Tkey>> orderLambda, bool isAsc = true) where T : class
212         {
213             int count = 0;
214             List<T> list = null;
215             count = db.Set<T>().Where(whereLambda).Count();
216             if (isAsc)
217             {
218                 var iQueryList = db.Set<T>().Where(whereLambda).OrderBy(orderLambda)
219                    .Skip((pageIndex - 1) * pageSize).Take(pageSize);
220 
221                 list = iQueryList.ToList();
222             }
223             else
224             {
225                 var iQueryList = db.Set<T>().Where(whereLambda).OrderByDescending(orderLambda)
226                  .Skip((pageIndex - 1) * pageSize).Take(pageSize);
227                 list = iQueryList.ToList();
228             }
229             rowCount = count;
230             return list;
231         }
232         #endregion
233 
234 
235         //2. SaveChange剝離出來,處理事務
236 
237         #region 01-批量處理SaveChange()
238         /// <summary>
239         /// 事務批量處理
240         /// </summary>
241         /// <returns></returns>
242         public int SaveChange()
243         {
244             return db.SaveChanges();
245         }
246         #endregion
247 
248         #region 02-新增
249         /// <summary>
250         /// 新增
251         /// </summary>
252         /// <param name="model">須要新增的實體</param>
253         public void AddNo<T>(T model) where T : class
254         {
255             db.Set<T>().Add(model);
256         }
257         #endregion
258 
259         #region 03-刪除
260         /// <summary>
261         /// 刪除
262         /// </summary>
263         /// <param name="model">須要刪除的實體</param>
264         public void DelNo<T>(T model) where T : class
265         {
266             db.Entry(model).State = EntityState.Deleted;
267         }
268         #endregion
269 
270         #region 04-根據條件刪除
271         /// <summary>
272         /// 條件刪除
273         /// </summary>
274         /// <param name="delWhere">須要刪除的條件</param>
275         public void DelByNo<T>(Expression<Func<T, bool>> delWhere) where T : class
276         {
277             List<T> listDels = db.Set<T>().Where(delWhere).ToList();
278             listDels.ForEach(d =>
279             {
280                 db.Set<T>().Attach(d);
281                 db.Set<T>().Remove(d);
282             });
283         }
284         #endregion
285 
286         #region 05-修改
287         /// <summary>
288         /// 修改
289         /// </summary>
290         /// <param name="model">修改後的實體</param>
291         public void ModifyNo<T>(T model) where T : class
292         {
293             db.Entry(model).State = EntityState.Modified;
294         }
295         #endregion
296 
297 
298         //3. EF調用sql語句
299 
300         #region 01-執行增長,刪除,修改操做(或調用存儲過程)
301         /// <summary>
302         /// 執行增長,刪除,修改操做(或調用存儲過程)
303         /// </summary>
304         /// <param name="sql"></param>
305         /// <param name="pars"></param>
306         /// <returns></returns>
307         public int ExecuteSql(string sql, params SqlParameter[] pars)
308         {
309             return db.Database.ExecuteSqlCommand(sql, pars);
310         }
311 
312         #endregion
313 
314         #region 02-執行查詢操做
315         /// <summary>
316         /// 執行查詢操做
317         /// </summary>
318         /// <typeparam name="T"></typeparam>
319         /// <param name="sql"></param>
320         /// <param name="pars"></param>
321         /// <returns></returns>
322         public List<T> ExecuteQuery<T>(string sql, params SqlParameter[] pars) where T : class
323         {
324             return db.Database.SqlQuery<T>(sql, pars).ToList();
325         }
326         #endregion
327 
328 
329 
330     }
331 }
BaseService類
  1 using System;
  2 using System.Collections.Generic;
  3 using System.Data.SqlClient;
  4 using System.Linq;
  5 using System.Linq.Expressions;
  6 using System.Text;
  7 using System.Threading.Tasks;
  8 
  9 namespace Ypf.IService
 10 {
 11     public interface IBaseService
 12     {
 13         //1. 直接提交數據庫
 14 
 15         #region 01-數據源
 16         IQueryable<T> Entities<T>() where T : class;
 17 
 18         #endregion
 19 
 20         #region 02-新增
 21         int Add<T>(T model) where T : class;
 22 
 23         #endregion
 24 
 25         #region 03-刪除(適用於先查詢後刪除 單個)
 26         /// <summary>
 27         /// 刪除(適用於先查詢後刪除的單個實體)
 28         /// </summary>
 29         /// <param name="model">須要刪除的實體</param>
 30         /// <returns></returns>
 31         int Del<T>(T model) where T : class;
 32 
 33         #endregion
 34 
 35         #region 04-根據條件刪除(支持批量刪除)
 36         /// <summary>
 37         /// 根據條件刪除(支持批量刪除)
 38         /// </summary>
 39         /// <param name="delWhere">傳入Lambda表達式(生成表達式目錄樹)</param>
 40         /// <returns></returns>
 41         int DelBy<T>(Expression<Func<T, bool>> delWhere) where T : class;
 42 
 43         #endregion
 44 
 45         #region 05-單實體修改
 46         /// <summary>
 47         /// 修改
 48         /// </summary>
 49         /// <param name="model">修改後的實體</param>
 50         /// <returns></returns>
 51         int Modify<T>(T model) where T : class;
 52 
 53         #endregion
 54 
 55         #region 06-批量修改(非lambda)
 56         /// <summary>
 57         /// 批量修改(非lambda)
 58         /// </summary>
 59         /// <param name="model">要修改實體中 修改後的屬性 </param>
 60         /// <param name="whereLambda">查詢實體的條件</param>
 61         /// <param name="proNames">lambda的形式表示要修改的實體屬性名</param>
 62         /// <returns></returns>
 63         int ModifyBy<T>(T model, Expression<Func<T, bool>> whereLambda, params string[] proNames) where T : class;
 64 
 65         #endregion
 66 
 67         #region 07-根據條件查詢
 68         /// <summary>
 69         /// 根據條件查詢
 70         /// </summary>
 71         /// <param name="whereLambda">查詢條件(lambda表達式的形式生成表達式目錄樹)</param>
 72         /// <returns></returns>
 73         List<T> GetListBy<T>(Expression<Func<T, bool>> whereLambda) where T : class;
 74 
 75         #endregion
 76 
 77         #region 08-根據條件排序和查詢
 78         /// <summary>
 79         /// 根據條件排序和查詢
 80         /// </summary>
 81         /// <typeparam name="Tkey">排序字段類型</typeparam>
 82         /// <param name="whereLambda">查詢條件</param>
 83         /// <param name="orderLambda">排序條件</param>
 84         /// <param name="isAsc">升序or降序</param>
 85         /// <returns></returns>
 86         List<T> GetListBy<T, Tkey>(Expression<Func<T, bool>> whereLambda, Expression<Func<T, Tkey>> orderLambda, bool isAsc = true) where T : class;
 87 
 88         #endregion
 89 
 90         #region 09-分頁查詢
 91         /// <summary>
 92         /// 根據條件排序和查詢
 93         /// </summary>
 94         /// <typeparam name="Tkey">排序字段類型</typeparam>
 95         /// <param name="pageIndex">頁碼</param>
 96         /// <param name="pageSize">頁容量</param>
 97         /// <param name="whereLambda">查詢條件</param>
 98         /// <param name="orderLambda">排序條件</param>
 99         /// <param name="isAsc">升序or降序</param>
100         /// <returns></returns>
101         List<T> GetPageList<T, Tkey>(int pageIndex, int pageSize, Expression<Func<T, bool>> whereLambda, Expression<Func<T, Tkey>> orderLambda, bool isAsc = true) where T : class;
102 
103         #endregion
104 
105         #region 10-分頁查詢輸出總行數
106         /// <summary>
107         /// 根據條件排序和查詢
108         /// </summary>
109         /// <typeparam name="Tkey">排序字段類型</typeparam>
110         /// <param name="pageIndex">頁碼</param>
111         /// <param name="pageSize">頁容量</param>
112         /// <param name="whereLambda">查詢條件</param>
113         /// <param name="orderLambda">排序條件</param>
114         /// <param name="isAsc">升序or降序</param>
115         /// <returns></returns>
116         List<T> GetPageList<T, Tkey>(int pageIndex, int pageSize, ref int rowCount, Expression<Func<T, bool>> whereLambda, Expression<Func<T, Tkey>> orderLambda, bool isAsc = true) where T : class;
117 
118         #endregion
119 
120 
121         //2. SaveChange剝離出來,處理事務
122 
123         #region 01-批量處理SaveChange()
124         /// <summary>
125         /// 事務批量處理
126         /// </summary>
127         /// <returns></returns>
128         int SaveChange();
129 
130         #endregion
131 
132         #region 02-新增
133         /// <summary>
134         /// 新增
135         /// </summary>
136         /// <param name="model">須要新增的實體</param>
137         void AddNo<T>(T model) where T : class;
138 
139         #endregion
140 
141         #region 03-刪除
142         /// <summary>
143         /// 刪除
144         /// </summary>
145         /// <param name="model">須要刪除的實體</param>
146         void DelNo<T>(T model) where T : class;
147 
148         #endregion
149 
150         #region 04-根據條件刪除
151         /// <summary>
152         /// 條件刪除
153         /// </summary>
154         /// <param name="delWhere">須要刪除的條件</param>
155         void DelByNo<T>(Expression<Func<T, bool>> delWhere) where T : class;
156 
157         #endregion
158 
159         #region 05-修改
160         /// <summary>
161         /// 修改
162         /// </summary>
163         /// <param name="model">修改後的實體</param>
164         void ModifyNo<T>(T model) where T : class;
165 
166         #endregion
167 
168 
169         //3. EF調用sql語句
170 
171         #region 01-執行增長,刪除,修改操做(或調用存儲過程)
172         /// <summary>
173         /// 執行增長,刪除,修改操做(或調用存儲過程)
174         /// </summary>
175         /// <param name="sql"></param>
176         /// <param name="pars"></param>
177         /// <returns></returns>
178         int ExecuteSql(string sql, params SqlParameter[] pars);
179 
180         #endregion
181 
182         #region 02-執行查詢操做
183         /// <summary>
184         /// 執行查詢操做
185         /// </summary>
186         /// <typeparam name="T"></typeparam>
187         /// <param name="sql"></param>
188         /// <param name="pars"></param>
189         /// <returns></returns>
190         List<T> ExecuteQuery<T>(string sql, params SqlParameter[] pars) where T : class;
191 
192         #endregion
193 
194     }
195 }
IBaseService接口

4. 利用Unity進行整合

  (1). 經過Nuget給【Ypf.Utils】層引入「Unity」的程序集和「Microsoft.AspNet.Mvc」程序集。

  (2). 新建類:DIFactory 用於讀取Unity配置文件建立Unity容器。須要引入程序集「System.Configuration」

        新建類:UnityControllerFactory 用於自定義控制器實例化工廠。須要引入程序集「System.Web」。

分享代碼:

 1 using Microsoft.Practices.Unity;
 2 using Microsoft.Practices.Unity.Configuration;
 3 using System;
 4 using System.Collections.Generic;
 5 using System.Configuration;
 6 using System.IO;
 7 using System.Linq;
 8 using System.Text;
 9 using System.Threading.Tasks;
10 using Unity;
11 
12 namespace Ypf.Utils
13 {
14     /// <summary>
15     /// 依賴注入工廠(單例的 採用雙if+lock鎖)
16     /// 讀取Unity的配置文件,並建立Unity容器
17     /// </summary>
18     public class DIFactory
19     {
20         //靜態的私有變量充當Lock鎖
21         private static object _lock = new object();
22         private static Dictionary<string, IUnityContainer> _UnityDictory = new Dictionary<string, IUnityContainer>();
23 
24         /// <summary>
25         /// 獲取Unity容器
26         /// </summary>
27         /// <param name="containerName">對應配置文件中節點的名稱,同時也當作字典中的key值</param>
28         /// <returns></returns>
29         public static IUnityContainer GetContainer(string containerName = "EFContainer")
30         {
31             if (!_UnityDictory.ContainsKey(containerName))
32             {
33                 lock (_lock)
34                 {
35                     if (!_UnityDictory.ContainsKey(containerName))
36                     {
37                         //1. 固定的4行代碼讀取配置文件
38                         ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
39                         fileMap.ExeConfigFilename = Path.Combine(AppDomain.CurrentDomain.BaseDirectory + "CfgFiles\\UnityConfig.xml");//找配置文件的路徑
40                         Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
41                         UnityConfigurationSection section = (UnityConfigurationSection)configuration.GetSection(UnityConfigurationSection.SectionName);
42                         //2. Unity層次的步驟
43                         IUnityContainer container = new UnityContainer();
44                         section.Configure(container, containerName);
45                         //3.將建立好的容器放到字典裏
46                         _UnityDictory.Add(containerName, container);
47                     }
48                 } 
49             }
50             return _UnityDictory[containerName];
51         }
52     }
53 }
DIFactory
 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading.Tasks;
 6 using System.Web.Mvc;
 7 using System.Web.Routing;
 8 using Unity;
 9 
10 namespace Ypf.Utils
11 {
12     /// <summary>
13     /// 自定義控制器實例化工廠
14     /// </summary>
15     public class UnityControllerFactory : DefaultControllerFactory
16     {
17         private IUnityContainer UnityContainer
18         {
19             get
20             {
21                 return DIFactory.GetContainer();
22             }
23         }
24 
25         /// <summary>
26         /// 建立控制器對象
27         /// </summary>
28         /// <param name="requestContext"></param>
29         /// <param name="controllerType"></param>
30         /// <returns></returns>
31         protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
32         {
33             if (null == controllerType)
34             {
35                 return null;
36             }
37             IController controller = (IController)this.UnityContainer.Resolve(controllerType);
38             return controller;
39         }
40 
41         /// <summary>
42         /// 釋放控制器
43         /// </summary>
44         /// <param name="controller"></param>
45         public override void ReleaseController(IController controller)
46         {
47             //this.UnityContainer.Teardown(controller);//釋放對象(老版本)
48 
49             base.ReleaseController(controller);
50         }
51     }
52 }
UnityControllerFactory

  (3). 經過Nuget給【Ypf.AdminWeb】層引入「Unity」的程序集,並新建CfgFiles文件夾和UnityConfig.xml文件,該xml文件須要改屬性爲「始終複製」。

分享代碼:

 1 <configuration>
 2   <configSections>
 3     <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Unity.Configuration"/>
 4   </configSections>
 5   <unity>
 6     <!-- unity容器配置註冊節點-->
 7     <containers>      
 8       <!--容器配置方式一:類型名稱和程序集名稱所有寫在容器中-->
 9       <container name="EFContainer">
10         <!--  type中的兩個參數分別是:類型名稱和DLL程序集的名稱 -->
11         <!--  mapTo中的兩個參數分別是:類型名稱和DLL程序集的名稱 -->
12         <!--
13           分析:這裏咱們須要使用的是TestService,但不直接使用它,而是使用它的接口,即將【mapTo】裏的類型註冊給【type】裏的類型
14         -->
15         <register type="Ypf.IService.ITestService,Ypf.IService" mapTo="Ypf.Service.TestService,Ypf.Service"/>
16         <register type="Ypf.IService.ITestService2,Ypf.IService" mapTo="Ypf.Service.TestService2,Ypf.Service"/>
17         <!--調用構造函數注入-->
18         <!--1.TestService須要依賴BaseService的構造函數,因此要對其進行注入-->
19         <register type="Ypf.IService.IBaseService,Ypf.IService" mapTo="Ypf.Service.BaseService, Ypf.Service"/>
20         <!--2.TestService須要傳入EF的上下文,因此要對其進行注入-->
21         <register type="System.Data.Entity.DbContext, EntityFramework" mapTo="Ypf.Data.MyDBContext1, Ypf.Data"  name="db"/>
22         <register type="System.Data.Entity.DbContext, EntityFramework" mapTo="Ypf.Data.MyDBContext2, Ypf.Data"  name="db2"/>
23 
24       </container>
25     </containers>
26   </unity>
27 </configuration>
UnityConfig.xml

  (4). 將【Ypf.Service】層的程序集生成路徑改成:..\Ypf.AdminWeb\bin\

  (5). 在【Ypf.AdminWeb】層中的Global文件中進行註冊 ,用Unity代替原有的控制器建立流程.

    //註冊自定義實例化控制器的容器(利用Unity代替原有的控制器建立流程)

     ControllerBuilder.Current.SetControllerFactory(new UnityControllerFactory());

 PS:橫向對比,AutoFac中也有一句相似的話:

  在【Ypf.AdminWeb】層測試Untiy的IOC和DI【測試經過】

5. 將Log4net整合到Ypf.Utils層中。

  (1). 經過Nuget給【Ypf.Utils】層添加「Log4net」程序集。

  (2). 新建Log文件,拷貝「log4net.xml」和「LogUtils.cs」兩個類文件,「log4net.xml」要改成嵌入的資源。

  (3). 在【Ypf.Admin】層的Global文件中進行註冊。LogUtils.InitLog4Net();

  (4). 解析:主要配置了兩種模式,輸出到「txt文本文檔」和「SQLServer數據庫中」。其中「文本文檔」又分了兩種模式,所有輸入到一個文檔中 和 不一樣類型的日誌輸入到不一樣文檔下,在調用的時候經過傳入參數來區分存放在哪一個文件夾下。

代碼詳見下面的實戰測試。

6. 完善【Ypf.Service】層中BaseService的封裝,封裝EF經常使用的增刪改查的方法,這裏暫時先不擴展EF插件的方法。

代碼見上

7.  如何控制EF上下文中的生命週期呢?

  在配置文件中能夠經過lifetime這個節點進行配置,而上一套框架的模式是直接經過using的模式進行配置,這裏可使用默認的方式:每次使用時候都建立。

詳見Unity專題:

  Unity深刻淺出(一)

  Unity深刻淺出(二)

 

三. 剖析核心

1. 相同數據庫結構,不一樣類型的數據庫如何快速切換。

    解析:首先須要明白的是不一樣的數據庫切換,實質上切換的就是 EF的上下文,該框架的模式EF的是使用Unity經過xxxService中子類的構造函數注入,須要在配置文件中配置構造函數注入EF上下文。

    <register type="System.Data.Entity.DbContext, EntityFramework" mapTo="Ypf.Data.MyDBContext1, Ypf.Data" />

 因此這裏切換數據庫(eg:SQLServer→MySQL)只須要經過Nuget引出EF對應數據庫的程序集,編寫好配置文件,將SQLServer的EF上下文(MyDbContext1)切換成MySQL的上下文便可。

【須要測試】

2. 在一個方法中如何同時訪問多個數據庫,並對其進行事務一體的增刪改操做。

 解析:首先須要在BaseService的構造函數參數拼寫多個DbContext參數,

 其次子類xxxService中一樣也須要多個DbContext參數,當多個參數時候,須要經過命名的方式指定注入,不然相互覆蓋,不能分別注入。

 

 最後,Unity的配置文件也須要經過命名的方式進行注入。

 

思考,Dependency特性寫在父類BaseService中是否能夠?

答案:經測試,不能夠,EF的命名方式的構造函數注入要寫在子類xxxService中。

同時會帶來一個弊端?

因爲BaseSevice類中泛型方法中的db,直接使用默認一個數據庫的時候的db屬性,全部致使當一個方法中若是涉及到多個上下文,無法直接使用BaseService中的封裝方法,須要寫原生代碼,有點麻煩。

以下圖:

那麼如何解決這個問題?

3. 鏈接多個數據庫框架的侷限性,如何改進。

  將BaseSevice中的泛型方法使用的db經過參數的形式進行傳入,並且默認爲一個數據庫時候對應的DbContext屬性,這樣當只有一個數據庫的時候,不用管它,由於他有默認值;當須要同時操控數據庫的時候,在子類XXXService中,根據須要傳入相應的db接口。

【經測試,不能夠,提示 默認參數必須是編譯時候的常量】

 後續將採用別的方案進行處理,請期待。

 

四. 實戰測試

這裏準備兩個數據庫,分別是:YpfFrame_DB 和 YpfFrameTest_DB

①:YpfFrame_DB中,用到了表:T_SysUser 和 T_SysLoginLog,表結構以下

②. YpfFrameTest_DB 表中用到了T_SchoolInfor,表結構以下

開始測試

1. 測試增刪改查,包括基本的事務一體。

在【Ypf.IService】層中新建ITestService接口,在【Ypf.Service】層中新建TestService類,實現ITestService接口, 定義TestBasicCRUD方法,進行測試,代碼以下。

 1          /// <summary>
 2         /// 1.測試基本的增刪改查,事務一體
 3         /// </summary>
 4         /// <returns></returns>
 5         public int TestBasicCRUD()
 6         {
 7             //1.增長操做
 8             T_SysUser t_SysUser = new T_SysUser()
 9             {
10                 id = Guid.NewGuid().ToString("N"),
11                 userAccount = "123456",
12                 userPwd = "XXX",
13                 userRealName = "XXX",
14                 appLoginNum = 1,
15                 addTime = DateTime.Now
16             };
17             this.AddNo<T_SysUser>(t_SysUser);
18 
19             //2.修改操做
20             T_SysLoginLog t_SysLoginLog = this.Entities<T_SysLoginLog>().Where(u => u.id == "1").FirstOrDefault();
21             if (t_SysLoginLog != null)
22             {
23                 t_SysLoginLog.userId = "xxx";
24                 t_SysLoginLog.userName = "xxx";
25                 this.ModifyNo<T_SysLoginLog>(t_SysLoginLog);
26             }
27             //3.提交操做
28             return db.SaveChanges();
29         }

2. 測試一個方法中查詢多個數據庫。

在ITestService接口中定義ConnectManyDB方法,並在TestService中實現該方法,代碼以下:

 

3. 測試一個方法中事務一體處理多個數據庫的crud操做。

 在ITestService接口中定義ManyDBTransaction方法,並在TestService中實現該方法,一樣須要在構造函數中注入多個EF上下文,代碼以下:

 1      [InjectionConstructor]
 2         public TestService([Dependency("db")]DbContext db, [Dependency("db2")]DbContext db2) : base(db, db2)
 3         {
 4 
 5         }
 6      /// <summary>
 7         /// 3. 同時對多個數據庫進行事務一體的CRUD操做
 8         /// 注:須要手動開啓msdtc服務(net start msdtc)
 9         /// </summary>
10         public void ManyDBTransaction()
11         {
12             using (TransactionScope trans = new TransactionScope())
13             {
14                 try
15                 {
16                     var data1 = db.Set<T_SysUser>().Where(u => u.id == "1").FirstOrDefault();
17                     if (data1 != null)
18                     {
19                         db.Set<T_SysUser>().Attach(data1);
20                         db.Set<T_SysUser>().Remove(data1);
21                         db.SaveChanges();
22                     }
23                     var data2 = db2.Set<T_SchoolInfor>().Where(u => u.id == "1").FirstOrDefault();
24                     if (data2 != null)
25                     {
26                         db2.Set<T_SchoolInfor>().Attach(data2);
27                         db2.Set<T_SchoolInfor>().Remove(data2);
28                         db2.SaveChanges();
29                     }
30 
31                     //最終提交事務
32                     trans.Complete();
33                 }
34                 catch (Exception ex)
35                 {
36                     var msg = ex.Message;
37                     //事務回滾
38                     Transaction.Current.Rollback();
39                     throw;
40                 }
41             }
42         }

  分析:同時鏈接多個數據庫,並對多個數據庫進行事務性的crud操做,這個時候必須用 【TransactionScope事務】須要引入System.Transactions程序集,前提要手動 【net start msdtc 】開啓對應服務,這樣整個事務經過「Complete」方法進行提交,經過Transaction.Current.Rollback()方法進行事務回滾,各自db的SaveChange不起做用,但仍是須要SaveChange的。

4. 測試xxxSevice子類中也能夠經過Unity進行IxxxService的屬性模式進行屬性的注入。

PS:爲了與前一節中AutoFac相呼應

 在【Ypf.IService】層中新建ITestService2接口,在【Ypf.Service】層中新建TestService2類,實現ITestService接口, 定義GetUserInfor方法,進行測試,代碼以下。

 1  public class TestService2 : BaseService, ITestService2
 2     {
 3         /// <summary>
 4         /// 調用父類的構造函數,這裏的db經過Unity的配置文件實現構造函數注入
 5         /// </summary>
 6         /// <param name="db"></param>
 7         [InjectionConstructor]
 8         public TestService2([Dependency("db")]DbContext db, [Dependency("db2")]DbContext db2) : base(db, db2)
 9         {
10 
11         }
12 
13         public List<T_SysUser> GetUserInfor()
14         {
15             return this.GetListBy<T_SysUser>(u => true);
16         }
17     }
View Code

在TestService中定義ITestService2屬性,以下:

 

在TestService中定義以下方法,內部用TestService2進行調用,能夠調用成功,從而證實xxxSevice子類中也能夠經過Unity進行IxxxService的模式進行「屬性的注入」。

 

5. 測試Log4net的分文件夾和不分文件的使用。

分享配置文件

  1 <?xml version="1.0" encoding="utf-8" ?>
  2 <configuration>
  3   <!-- 一. 添加log4net的自定義配置節點-->
  4   <configSections>
  5     <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net" />
  6   </configSections>
  7   <!--二. log4net的核心配置代碼-->
  8   <log4net>
  9     <!--1. 輸出途徑(一) 將日誌以回滾文件的形式寫到文件中-->
 10     
 11     <!--模式一:所有存放到一個文件夾裏-->
 12     <appender name="log0" type="log4net.Appender.RollingFileAppender">
 13       <!--1.1 文件夾的位置(也能夠寫相對路徑)-->
 14       <param name="File"  value="D:\MyLog\" />
 15       <!--相對路徑-->
 16       <!--<param name="File"  value="Logs/" />-->
 17       <!--1.2 是否追加到文件-->
 18       <param name="AppendToFile" value="true" />
 19       <!--1.3 使用最小鎖定模型(minimal locking model),以容許多個進程能夠寫入同一個文件 -->
 20       <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
 21       <!--1.4 配置Unicode編碼-->
 22       <Encoding value="UTF-8" />
 23       <!--1.5 是否只寫到一個文件裏-->
 24       <param name="StaticLogFileName" value="false" />
 25       <!--1.6 配置按照何種方式產生多個日誌文件 (Date:日期、Size:文件大小、Composite:日期和文件大小的混合方式)-->
 26       <param name="RollingStyle" value="Composite" />
 27       <!--1.7 介紹多種日誌的的命名和存放在磁盤的形式-->
 28       <!--1.7.1 在根目錄下直接以日期命名txt文件 注意&quot;的位置,去空格 -->
 29       <param name="DatePattern" value="yyyy-MM-dd&quot;.log&quot;" />
 30       <!--1.7.2 在根目錄下按日期產生文件夾,文件名固定 test.log  -->
 31       <!--<param name="DatePattern" value="yyyy-MM-dd/&quot;test.log&quot;"  />-->
 32       <!--1.7.3 在根目錄下按日期產生文件夾,這是按日期產生文件夾,並在文件名前也加上日期  -->
 33       <!--<param name="DatePattern" value="yyyyMMdd/yyyyMMdd&quot;-test.log&quot;"  />-->
 34       <!--1.7.4 在根目錄下按日期產生文件夾,這再造成下一級固定的文件夾  -->
 35       <!--<param name="DatePattern" value="yyyyMMdd/&quot;OrderInfor/test.log&quot;"  />-->
 36       <!--1.8 配置每一個日誌的大小。【只在1.6 RollingStyle 選擇混合方式與文件大小方式下才起做用!!!】可用的單位:KB|MB|GB。不要使用小數,不然會一直寫入當前日誌,
 37       超出大小後在全部文件名後自動增長正整數從新命名,數字最大的最先寫入。-->
 38       <param name="maximumFileSize" value="10MB" />
 39       <!--1.9 最多產生的日誌文件個數,超過則保留最新的n個 將value的值設置-1,則不限文件個數 【只在1.6 RollingStyle 選擇混合方式與文件大小方式下才起做用!!!】
 40         與1.8中maximumFileSize文件大小是配合使用的-->
 41       <param name="MaxSizeRollBackups" value="5" />
 42       <!--1.10 配置文件文件的佈局格式,使用PatternLayout,自定義佈局-->
 43       <layout type="log4net.Layout.PatternLayout">
 44         <conversionPattern value="記錄時間:%date %n線程ID:[%thread] %n日誌級別:%-5level %n出錯類:%logger property: [%property{NDC}] - %n錯誤描述:%message%newline %n%newline"/>
 45       </layout>
 46     </appender>
 47 
 48     <!--模式二:分文件夾存放-->
 49     <!--文件夾1-->
 50     <appender name="log1" type="log4net.Appender.RollingFileAppender">
 51       <param name="File"  value="D:\MyLog\OneLog\" />
 52       <param name="AppendToFile" value="true" />
 53       <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
 54       <Encoding value="UTF-8" />
 55       <param name="StaticLogFileName" value="false" />
 56       <param name="RollingStyle" value="Composite" />
 57       <param name="DatePattern" value="yyyy-MM-dd&quot;.log&quot;" />
 58       <param name="maximumFileSize" value="10MB" />
 59       <param name="MaxSizeRollBackups" value="5" />
 60       <layout type="log4net.Layout.PatternLayout">
 61         <conversionPattern value="%message%newline" />
 62       </layout>
 63       <!--下面是利用過濾器進行分文件夾存放,兩種過濾器進行配合-->
 64       <!--與Logger名稱(OneLog)匹配,才記錄,-->
 65       <filter type="log4net.Filter.LoggerMatchFilter">
 66         <loggerToMatch value="OneLog" />
 67       </filter>
 68       <!--阻止全部的日誌事件被記錄-->
 69       <filter type="log4net.Filter.DenyAllFilter" />
 70     </appender>
 71     <!--文件夾2-->
 72     <appender name="log2" type="log4net.Appender.RollingFileAppender">
 73       <param name="File"  value="D:\MyLog\TwoLog\" />
 74       <param name="AppendToFile" value="true" />
 75       <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
 76       <Encoding value="UTF-8" />
 77       <param name="StaticLogFileName" value="false" />
 78       <param name="RollingStyle" value="Composite" />
 79       <param name="DatePattern" value="yyyy-MM-dd&quot;.log&quot;" />
 80       <param name="maximumFileSize" value="10MB" />
 81       <param name="MaxSizeRollBackups" value="5" />
 82       <layout type="log4net.Layout.PatternLayout">
 83         <conversionPattern value="%message%newline" />
 84       </layout>
 85       <!--下面是利用過濾器進行分文件夾存放,兩種過濾器進行配合-->
 86       <!--與Logger名稱(TwoLog)匹配,才記錄,-->
 87       <filter type="log4net.Filter.LoggerMatchFilter">
 88         <loggerToMatch value="TwoLog" />
 89       </filter>
 90       <!--阻止全部的日誌事件被記錄-->
 91       <filter type="log4net.Filter.DenyAllFilter" />
 92     </appender>
 93 
 94 
 95     <!--2. 輸出途徑(二) 記錄日誌到數據庫-->
 96     <appender name="AdoNetAppender" type="log4net.Appender.AdoNetAppender">
 97       <!--2.1 設置緩衝區大小,只有日誌記錄超設定值纔會一塊寫入到數據庫-->
 98       <param name="BufferSize" value="1" />
 99       <!--2.2 引用-->
100       <connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
101       <!--2.3 數據庫鏈接字符串-->
102       <connectionString value="data source=localhost;initial catalog=LogDB;integrated security=false;persist security info=True;User ID=sa;Password=123456" />
103       <!--2.4 SQL語句插入到指定表-->
104       <commandText value="INSERT INTO LogInfor ([threadId],[log_level],[log_name],[log_msg],[log_exception],[log_time]) VALUES (@threadId, @log_level, @log_name, @log_msg, @log_exception,@log_time)" />
105       <!--2.5 數據庫字段匹配-->
106       <!-- 線程號-->
107       <parameter>
108         <parameterName value="@threadId" />
109         <dbType value="String" />
110         <size value="100" />
111         <layout type="log4net.Layout.PatternLayout">
112           <conversionPattern value="%thread" />
113         </layout>
114       </parameter>
115       <!--日誌級別-->
116       <parameter>
117         <parameterName value="@log_level" />
118         <dbType value="String" />
119         <size value="100" />
120         <layout type="log4net.Layout.PatternLayout">
121           <conversionPattern value="%level" />
122         </layout>
123       </parameter>
124       <!--日誌記錄類名稱-->
125       <parameter>
126         <parameterName value="@log_name" />
127         <dbType value="String" />
128         <size value="100" />
129         <layout type="log4net.Layout.PatternLayout">
130           <conversionPattern value="%logger" />
131         </layout>
132       </parameter>
133       <!--日誌信息-->
134       <parameter>
135         <parameterName value="@log_msg" />
136         <dbType value="String" />
137         <size value="5000" />
138         <layout type="log4net.Layout.PatternLayout">
139           <conversionPattern value="%message" />
140         </layout>
141       </parameter>
142       <!--異常信息  指的是如Infor 方法的第二個參數的值-->
143       <parameter>
144         <parameterName value="@log_exception" />
145         <dbType value="String" />
146         <size value="2000" />
147         <layout type="log4net.Layout.ExceptionLayout" />
148       </parameter>
149       <!-- 日誌記錄時間-->
150       <parameter>
151         <parameterName value="@log_time" />
152         <dbType value="DateTime" />
153         <layout type="log4net.Layout.RawTimeStampLayout" />
154       </parameter>
155     </appender>
156 
157 
158     <!--(二). 配置日誌的的輸出級別和加載日誌的輸出途徑-->
159     <root>
160       <!--1. level中的value值表示該值及其以上的日誌級別纔會輸出-->
161       <!--OFF > FATAL(致命錯誤) > ERROR(通常錯誤) > WARN(警告) > INFO(通常信息) > DEBUG(調試信息)  > ALL  -->
162       <!--OFF表示全部信息都不寫入,ALL表示全部信息都寫入-->
163       <level value="ALL"></level>
164       <!--2. append-ref標籤表示要加載前面的日誌輸出途徑代碼  經過ref和appender標籤的中name屬性相關聯-->
165       
166       <appender-ref ref="log0"></appender-ref>
167       <appender-ref ref="log1"></appender-ref>
168       <appender-ref ref="log2"></appender-ref>
169 
170       <!--<appender-ref ref="AdoNetAppender"></appender-ref>-->
171     </root>
172   </log4net>
173 
174 </configuration>
View Code

分享對應幫助類封裝

  1 using log4net;
  2 using System;
  3 using System.Collections.Generic;
  4 using System.Diagnostics;
  5 using System.Linq;
  6 using System.Reflection;
  7 using System.Text;
  8 using System.Threading.Tasks;
  9 
 10 namespace Ypf.Utils.Log
 11 {
 12     public class LogUtils
 13     {
 14         //聲明文件夾名稱(這裏分兩個文件夾)
 15         static string log1Name = "OneLog";
 16         static string log2Name = "TwoLog";
 17 
 18         //能夠聲明多個日誌對象
 19         //模式一:不分文件夾(全部的log對存放在這一個文件夾下)
 20         public static ILog log = LogManager.GetLogger(typeof(LogUtils));
 21 
 22         //模式二:分文件夾
 23         //若是是要分文件夾存儲,這裏的名稱須要和配置文件中loggerToMatch節點中的value相配合
 24         //1. OneLog文件夾
 25         public static ILog log1 = LogManager.GetLogger(log1Name);
 26         //2. TwoLog文件夾
 27         public static ILog log2 = LogManager.GetLogger(log2Name);
 28 
 29         #region 01-初始化Log4net的配置
 30         /// <summary>
 31         /// 初始化Log4net的配置
 32         /// xml文件必定要改成嵌入的資源
 33         /// </summary>
 34         public static void InitLog4Net()
 35         {
 36             Assembly assembly = Assembly.GetExecutingAssembly();
 37             var xml = assembly.GetManifestResourceStream("Ypf.Utils.Log.log4net.xml");
 38             log4net.Config.XmlConfigurator.Configure(xml);
 39         }
 40         #endregion
 41 
 42         /************************* 五種不一樣日誌級別 *******************************/
 43         //FATAL(致命錯誤) > ERROR(通常錯誤) > WARN(警告) > INFO(通常信息) > DEBUG(調試信息)
 44 
 45         #region 00-將調試的信息輸出,能夠定位到具體的位置(解決高層封裝帶來的問題)
 46         /// <summary>
 47         /// 將調試的信息輸出,能夠定位到具體的位置(解決高層封裝帶來的問題)
 48         /// </summary>
 49         /// <returns></returns>
 50         private static string getDebugInfo()
 51         {
 52             StackTrace trace = new StackTrace(true);
 53             return trace.ToString();
 54         }
 55         #endregion
 56 
 57         #region 01-DEBUG(調試信息)
 58         /// <summary>
 59         /// DEBUG(調試信息)
 60         /// </summary>
 61         /// <param name="msg">日誌信息</param>
 62         ///  <param name="logName">文件夾名稱</param>
 63         public static void Debug(string msg, string logName = "")
 64         {
 65             if (logName == "")
 66             {
 67                 log.Debug(getDebugInfo() + msg);
 68             }
 69             else if (logName == log1Name)
 70             {
 71                 log1.Debug(msg);
 72             }
 73             else if (logName == log2Name)
 74             {
 75                 log2.Debug(msg);
 76             }
 77         }
 78         /// <summary>
 79         /// Debug
 80         /// </summary>
 81         /// <param name="msg">日誌信息</param>
 82         /// <param name="exception">錯誤信息</param>
 83         public static void Debug(string msg, Exception exception)
 84         {
 85             log.Debug(getDebugInfo() + msg, exception);
 86         }
 87 
 88         #endregion
 89 
 90         #region 02-INFO(通常信息)
 91         /// <summary>
 92         /// INFO(通常信息)
 93         /// </summary>
 94         /// <param name="msg">日誌信息</param>
 95         /// <param name="logName">文件夾名稱</param>
 96         public static void Info(string msg, string logName = "")
 97         {
 98             if (logName == "")
 99             {
100                 log.Info(getDebugInfo() + msg);
101             }
102             else if (logName == log1Name)
103             {
104                 log1.Info(msg);
105             }
106             else if (logName == log2Name)
107             {
108                 log2.Info(msg);
109             }
110         }
111         /// <summary>
112         /// Info
113         /// </summary>
114         /// <param name="msg">日誌信息</param>
115         /// <param name="exception">錯誤信息</param>
116         public static void Info(string msg, Exception exception)
117         {
118             log.Info(getDebugInfo() + msg, exception);
119         }
120         #endregion
121 
122         #region 03-WARN(警告)
123         /// <summary>
124         ///WARN(警告)
125         /// </summary>
126         /// <param name="msg">日誌信息</param>
127         /// <param name="logName">文件夾名稱</param>
128         public static void Warn(string msg, string logName = "")
129         {
130             if (logName == "")
131             {
132                 log.Warn(getDebugInfo() + msg);
133             }
134             else if (logName == log1Name)
135             {
136                 log1.Warn(msg);
137             }
138             else if (logName == log2Name)
139             {
140                 log2.Warn(msg);
141             }
142         }
143         /// <summary>
144         /// Warn
145         /// </summary>
146         /// <param name="msg">日誌信息</param>
147         /// <param name="exception">錯誤信息</param>
148         public static void Warn(string msg, Exception exception)
149         {
150             log.Warn(getDebugInfo() + msg, exception);
151         }
152         #endregion
153 
154         #region 04-ERROR(通常錯誤)
155         /// <summary>
156         /// ERROR(通常錯誤)
157         /// </summary>
158         /// <param name="msg">日誌信息</param>
159         /// <param name="logName">文件夾名稱</param>
160         public static void Error(string msg, string logName = "")
161         {
162             if (logName == "")
163             {
164                 log.Error(getDebugInfo() + msg);
165             }
166             else if (logName == log1Name)
167             {
168                 log1.Error(msg);
169             }
170             else if (logName == log2Name)
171             {
172                 log2.Error(msg);
173             }
174         }
175         /// <summary>
176         /// Error
177         /// </summary>
178         /// <param name="msg">日誌信息</param>
179         /// <param name="exception">錯誤信息</param>
180         public static void Error(string msg, Exception exception)
181         {
182             log.Error(getDebugInfo() + msg, exception);
183         }
184         #endregion
185 
186         #region 05-FATAL(致命錯誤)
187         /// <summary>
188         /// FATAL(致命錯誤)
189         /// </summary>
190         /// <param name="msg">日誌信息</param>
191         /// <param name="logName">文件夾名稱</param>
192         public static void Fatal(string msg, string logName = "")
193         {
194             if (logName == "")
195             {
196                 log.Fatal(getDebugInfo() + msg);
197             }
198             else if (logName == log1Name)
199             {
200                 log1.Fatal(msg);
201             }
202             else if (logName == log2Name)
203             {
204                 log2.Fatal(msg);
205             }
206         }
207         /// <summary>
208         /// Fatal
209         /// </summary>
210         /// <param name="msg">日誌信息</param>
211         /// <param name="exception">錯誤信息</param>
212         public static void Fatal(string msg, Exception exception)
213         {
214             log.Fatal(getDebugInfo() + msg, exception);
215         }
216 
217         #endregion
218 
219 
220 
221     }
222 }
View Code

代碼測試

 

五. 後續

  後續將對比 Unity和AutoFac,對比這兩套框架的搭建模式。

 

 

 

 

 

!

  • 做       者 : Yaopengfei(姚鵬飛)
  • 博客地址 : http://www.cnblogs.com/yaopengfei/
  • 聲     明1 : 本人才疏學淺,用郭德綱的話說「我是一個小學生」,若有錯誤,歡迎討論,請勿謾罵^_^。
  • 聲     明2 : 原創博客請在轉載時保留原文連接或在文章開頭加上本人博客地址,不然保留追究法律責任的權利。
相關文章
相關標籤/搜索