C#基於介面設計三層架構Unity篇

来源:https://www.cnblogs.com/atomy/archive/2020/03/21/12537337.html
-Advertisement-
Play Games

一、引言 面向介面(抽象)編程,是為了降低程式的耦合度,符合依賴倒置原則。因此典型的三層架構UI、BLL、DAL基於介面設計後,會拓展成UI、IBLL、BLL、IDAL、DAL。在上一篇《C# IoC學習筆記》中我們可以瞭解到,控制反轉(IoC)使對象的創建交給了第三方IoC容器如Unity。利用U ...


    一、引言

    面向介面(抽象)編程,是為了降低程式的耦合度,符合依賴倒置原則。因此典型的三層架構UI、BLL、DAL基於介面設計後,會拓展成UI、IBLL、BLL、IDAL、DAL。在上一篇《C# IoC學習筆記》中我們可以瞭解到,控制反轉(IoC)使對象的創建交給了第三方IoC容器如Unity。利用Unity的IoC功能,可以對基於介面設計的三層架構做進一步的升級,搭建一個更容易實現的可配置可擴展的三層架構;利用Unity的AOP功能,使框架更加的簡潔,因為它抽出了框架的公共邏輯部分。

    二、項目建立

    2.1、項目建立

    依次新建項目UI(Client)、IBLL、BLL、IDAL、DAL、Model、Common。

    2.2項目說明

    三、項目之間的引用關係

    3.1、對著項目名稱右鍵->添加->引用->項目,添加各個項目的引用。

    3.2、引用說明

    四、項目需安裝的NuGet包

 

     五、註意事項

    對Unity容器的IoC調用進行封裝,Container應封裝成單例模式以提高效率,此處使用MemoryCache。

    5.1、在Common項目引用System.Runtime.Caching.dll,併在Helper文件夾下新建一個緩存幫助類:MemoryCacheHelper.cs。

    /// <summary>
    /// 記憶體緩存幫助類,支持絕對過期時間、滑動過期時間、文件依賴三種緩存方式。
    /// </summary>
    class MemoryCacheHelper
    {
        private static readonly object _locker1 = new object(), _locker2 = new object();

        /// <summary>
        /// 取緩存項,如果不存在則返回空。
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public static T GetCacheItem<T>(string key)
        {
            try
            {
                return (T)MemoryCache.Default[key];
            }
            catch
            {
                return default(T);
            }
        }

        /// <summary>
        /// 是否包含指定鍵的緩存項
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static bool Contains(string key)
        {
            return MemoryCache.Default.Contains(key);
        }

        /// <summary>
        /// 取緩存項,如果不存在則新增緩存項。
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="cachePopulate"></param>
        /// <param name="slidingExpiration"></param>
        /// <param name="absoluteExpiration"></param>
        /// <returns></returns>
        public static T GetOrAddCacheItem<T>(string key, Func<T> cachePopulate, TimeSpan? slidingExpiration = null, DateTime? absoluteExpiration = null)
        {
            if (string.IsNullOrWhiteSpace(key)) throw new ArgumentException("Invalid cache key");
            if (cachePopulate == null) throw new ArgumentNullException("cachePopulate");
            if (slidingExpiration == null && absoluteExpiration == null) throw new ArgumentException("Either a sliding expiration or absolute must be provided");

            if (MemoryCache.Default[key] == null)
            {
                lock (_locker1)
                {
                    if (MemoryCache.Default[key] == null)
                    {
                        T cacheValue = cachePopulate();
                        if (!typeof(T).IsValueType && cacheValue == null)   //如果是引用類型且為NULL則不存緩存
                        {
                            return cacheValue;
                        }

                        var item = new CacheItem(key, cacheValue);
                        var policy = CreatePolicy(slidingExpiration, absoluteExpiration);

                        MemoryCache.Default.Add(item, policy);
                    }
                }
            }

            return (T)MemoryCache.Default[key];
        }

        /// <summary>
        /// 取緩存項,如果不存在則新增緩存項。
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="cachePopulate"></param>
        /// <param name="dependencyFilePath"></param>
        /// <returns></returns>
        public static T GetOrAddCacheItem<T>(string key, Func<T> cachePopulate, string dependencyFilePath)
        {
            if (string.IsNullOrWhiteSpace(key)) throw new ArgumentException("Invalid cache key");
            if (cachePopulate == null) throw new ArgumentNullException("cachePopulate");

            if (MemoryCache.Default[key] == null)
            {
                lock (_locker2)
                {
                    if (MemoryCache.Default[key] == null)
                    {
                        T cacheValue = cachePopulate();
                        if (!typeof(T).IsValueType && cacheValue == null)   //如果是引用類型且為NULL則不存緩存
                        {
                            return cacheValue;
                        }

                        var item = new CacheItem(key, cacheValue);
                        var policy = CreatePolicy(dependencyFilePath);

                        MemoryCache.Default.Add(item, policy);
                    }
                }
            }

            return (T)MemoryCache.Default[key];
        }

        /// <summary>
        /// 指定緩存項的一組逐出和過期詳細信息
        /// </summary>
        /// <param name="slidingExpiration"></param>
        /// <param name="absoluteExpiration"></param>
        /// <returns></returns>
        private static CacheItemPolicy CreatePolicy(TimeSpan? slidingExpiration, DateTime? absoluteExpiration)
        {
            var policy = new CacheItemPolicy();

            if (absoluteExpiration.HasValue)
            {
                policy.AbsoluteExpiration = absoluteExpiration.Value;
            }
            else if (slidingExpiration.HasValue)
            {
                policy.SlidingExpiration = slidingExpiration.Value;
            }

            policy.Priority = CacheItemPriority.Default;

            return policy;
        }

        /// <summary>
        /// 指定緩存項的一組逐出和過期詳細信息
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        private static CacheItemPolicy CreatePolicy(string filePath)
        {
            CacheItemPolicy policy = new CacheItemPolicy();
            policy.ChangeMonitors.Add(new HostFileChangeMonitor(new List<string>() { filePath }));
            policy.Priority = CacheItemPriority.Default;
            return policy;
        }

        /// <summary>
        /// 移除指定鍵的緩存項
        /// </summary>
        /// <param name="key"></param>
        public static void RemoveCacheItem(string key)
        {
            if (Contains(key))
            {
                MemoryCache.Default.Remove(key);
            }
        }
    }
View Code

    5.2、在Common項目Helper文件夾下麵新建一個Unity幫助類:UnityHelper.cs,並實現Container的緩存。

    /// <summary>
    /// Unity容器幫助類
    /// </summary>
    public static class UnityHelper
    {
        /// <summary>
        /// Unity容器創建對象(不含別名)
        /// </summary>
        /// <param name="containerName">容器名稱</param>
        /// <returns></returns>
        public static T GetObject<T>(string containerName)
        {
            IUnityContainer container = MemoryCacheHelper.GetOrAddCacheItem(containerName, () =>
            {
                IUnityContainer unityContainer = new UnityContainer();
                ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap
                {
                    ExeConfigFilename = Path.Combine(AppDomain.CurrentDomain.BaseDirectory + @"ConfigFiles\Unity.config")
                };
                Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
                UnityConfigurationSection configSection = (UnityConfigurationSection)configuration.GetSection(UnityConfigurationSection.SectionName);
                configSection.Configure(unityContainer, containerName);
                return unityContainer;
            },TimeSpan.FromMinutes(30),null);
            
            return container.Resolve<T>();
        }

        /// <summary>
        /// Unity容器創建對象(含別名)
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="containerName">容器名稱</param>
        /// <param name="alisName">對象別名</param>
        /// <returns></returns>
        public static T GetObject<T>(string containerName, string alisName)
        {
            IUnityContainer container = MemoryCacheHelper.GetOrAddCacheItem(containerName, () =>
            {
                IUnityContainer unityContainer = new UnityContainer();
                ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap
                {
                    ExeConfigFilename = Path.Combine(AppDomain.CurrentDomain.BaseDirectory + @"ConfigFiles\Unity.config")
                };
                Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
                UnityConfigurationSection configSection = (UnityConfigurationSection)configuration.GetSection(UnityConfigurationSection.SectionName);
                configSection.Configure(unityContainer, containerName);
                return unityContainer;
            }, TimeSpan.FromMinutes(30), null);

            return container.Resolve<T>(alisName);
        }
    }
View Code

 

    源碼下載


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 大家在學習Python的時候,有人會問“Python要學到什麼程度才能出去找工作”,對於在Python培訓機構學習Python的同學來說這都不是問題,因為按照Python課程大綱來,一般都不會有什麼問題,而對於自學Python來說,那就比較難掌握,冒然出去找工作非常容易受打擊,從而失去學習Pytho ...
  • 1、Go 語言最主要的特性 自動垃圾回收 更豐富的內置類型 函數多返回值 錯誤處理 匿名函數和閉包 類型和介面 併發編程 反射 語言交互性 2、$GOPATH目錄約定有三個子目錄 src存放源代碼(比如:.go .c .h .s等) 按照golang預設約定,go run,go install等命令 ...
  • 關鍵詞:鄭州 二本 物理專業 先前端實習生 後Java程式員 更多文章收錄在碼雲倉庫:https://gitee.com/bingqilinpeishenme/Java Tutorials 前言 沒有正式復工,就一直在老家待著,已經很長時間沒有在三月份時候待在老家了,好久好久,從08年去縣城上高中開 ...
  • 問題背景 使用mybatis-plus進行資料庫交互,預設開啟null不更新設置,在新增數據後,編輯頁面將欄位值清除後(date類型,int類型,為避免預設值傳入,model全部使用包裝類型初始化為null)無法將null值更新至資料庫 單個解決方案 通過UpdateWrapper的set方法強制字 ...
  • Spring 整合 Mybatis 在開始使用 MyBatis Spring 之前,需要先熟悉 Spring 和 MyBatis 這兩個框架和有關它們的術語。 MyBatis Spring 需要以下版本: | MyBatis Spring | MyBatis | Spring 框架 | Spring ...
  • Startup構造函數 ConfigureServices方法 Configure方法 在ConfigureWebHostDefaults中直接配置服務和請求管道 ASP.NET Core一般使用Startup類來進行應用的配置。在構建應用主機時指定Startup類,通常通過在主機生成器上調用Web ...
  • 前言 為什麼在開發中,介面文檔越來越成為前後端開發人員溝通的樞紐呢? 隨著業務的發張,項目越來越多,而對於支撐整個項目架構體系而言,我們對系統業務的水平拆分,垂直分層,讓業務系統更加清晰,從而產生一系統平臺和系統,並使用介面進行數據交互。因此可見,業務的不斷發展,介面不斷增多,很多介面各自寄宿在不同 ...
  • 記錄更改控制項外觀學習 更改控制項外觀有三種方法:屬性、Style、ControlTemplate。 Style:可以一次對多個控制項設置屬性。 ContentTemplate: 自定義Control外觀,利用行為更改外觀。 屬性:<Window x:Class="WpfApp1.MainWindow" ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...