Winform開發框架的業務對象統一調用方式


在這個紛繁的社會里面,統一性的特點能夠帶來很多高效的產出、牢固的記憶,這種特征無論對於企業、個人的開發工作,知識的傳承都有着非常重要的作用,Winfrom框架本身就是基於這個理念而生,從統一的數據庫設計規則開始,統一的項目格局,統一的業務類、數據訪問類、實體類繼承關系,再到統一的公用類庫,統一的權限管理模塊,統一的字典管理模塊,統一的附件管理...,理解這些理念和規則后,再來個終極的統一,框架代碼快速生成--Database2Sharp代碼生成工具。所有的框架(包括傳統Winform開發框架、WCF開發框架、混合式開發框架、Web開發框架)都融合到這里來,統一整合各種看似零散,實則高度滲透的模塊,統一的步伐除了時間、效力外,帶來給我更多的饋贈。本文主要介紹我的Winform框架(也包括其他框架的特點)的業務對象統一調用的方式,介紹如何通過BLLFactory或者CallerFactory的公用類庫來實現各種業務對象的創建工作。

1、BLLFactory的對象統一調用規則

在我的框架里面,所有的業務類調用都是以BLLFactory入口進行開始創建,傳遞業務對象進去即可創建,這種統一入口的方式能夠方便記憶,並減少代碼,更重要的是能夠很好把一些如緩存規則、創建規則封裝起來,簡化代碼。BLLFactory的創建示意圖如下所示。

既然是統一調用規則方式,那么BLLFactory的類庫就應該提升到公用類庫的級別,所以提供Winform框架支持的公用類庫如下所示。

當然,為了減少代碼,提高開發效率,整體的框架處處體現了代碼重用的規則,盡可能把重復的代碼提取出來,因此還有很多如數據訪問基類、業務訪問基類、數據訪問基類接口、實體基類等類庫,結合泛型能夠使我們的API更加統一化、強類型化,提高開發效率。由於BLLFactory是公用類庫級別,所有獨立開發的模塊,也都是以該類庫為統一入口,創建所必須的對象。

我們看看框架如何能夠在紛繁復雜的類庫里面,准確創建一系列的對象的。

BLLFactory業務對象工廠輔助類的代碼如下所示。

    /// <summary>
    /// 對業務類進行構造的工廠類
    /// </summary>
    /// <typeparam name="T">業務對象類型</typeparam>
    public class BLLFactory<T> where T : class
    {
        private static Hashtable objCache = new Hashtable();
        private static object syncRoot = new Object();

        /// <summary>
        /// 創建或者從緩存中獲取對應業務類的實例
        /// </summary>
        public static T Instance
        {
            get
            {
                string CacheKey = typeof(T).FullName;
                T bll = (T)objCache[CacheKey];  //從緩存讀取  
                if (bll == null)
                {
                    lock (syncRoot)
                    {
                        if (bll == null)
                        {
                            bll = Reflect<T>.Create(typeof(T).FullName, typeof(T).Assembly.GetName().Name); //反射創建,並緩存
                            objCache.Add(typeof(T).FullName, bll);
                        }
                    }
                }
                return bll;
            }
        }
    }

其中利用了哈希表對象對創建的對象進行緩存,並進一步傳遞參數給Reflect公用類庫,對指定對象全名、程序集的業務對象進行創建。

以上只是很薄的一層關系,一般我們都能夠很容易理解,但是我們知道,每個業務對象類,還需要負責創建里面的數據訪問基類(如IUser接口的數據訪問基類userDal),我們來繼續分析BaseBLL對象的工作邏輯,才能很好理解其中的關系。

    /// <summary>
    /// 用戶信息業務管理類
    /// </summary>
    public class User : BaseBLL<UserInfo>
    {
        private IUser userDal;

        public User() : base()
        {
            base.Init(this.GetType().FullName, System.Reflection.Assembly.GetExecutingAssembly().GetName().Name);
            this.userDal = (IUser)base.baseDal;
        }
        ..............................

    }

其中Init的函數接口定義如下,主要就是根據相關參數,構建數據不同的數據訪問對象,如SqlServer的訪問對象,或者Oracle的數據訪問對象等。

        /// <summary>
        /// 參數賦值后,初始化相關對象
        /// </summary>
        /// <param name="bllFullName">BLL業務類的全名(子類必須實現),子類構造函數傳入this.GetType().FullName</param>
        /// <param name="dalAssemblyName">數據訪問層程序集的清單文件的文件名,不包括其擴展名,可使用Assembly.GetExecutingAssembly().GetName().Name</param>
        /// <param name="bllPrefix">BLL命名空間的前綴(BLL.)</param>
        void Init(string bllFullName, string dalAssemblyName, string bllPrefix = "BLL.")

由於數據訪問也是基於反射方式(帶緩存)創建,因此需要知道數據訪問類的全名和對應的程序集,如果整合在一個項目工程里面,如我的框架結構代碼所示,那么dalAssemblyName就是System.Reflection.Assembly.GetExecutingAssembly().GetName().Name了。其中Init函數主要就是根據配置的數據庫類型,創建指定類型的數據訪問業務對象,主要的邏輯代碼如下所示。

            #region 根據不同的數據庫類型,構造相應的DAL層
            AppConfig config = new AppConfig();
            string dbType = config.AppConfigGet("ComponentDbType");
            if (string.IsNullOrEmpty(dbType))
            {
                dbType = "sqlserver";
            }
            dbType = dbType.ToLower();

            string DALPrefix = "";
            if (dbType == "sqlserver")
            {
                DALPrefix = "DALSQL.";
            }
            else if (dbType == "access")
            {
                DALPrefix = "DALAccess.";
            }
            else if (dbType == "oracle")
            {
                DALPrefix = "DALOracle.";
            }
            else if (dbType == "sqlite")
            {
                DALPrefix = "DALSQLite.";
            }
            else if (dbType == "mysql")
            {
                DALPrefix = "DALMySql.";
            }
            #endregion

            this.dalName = bllFullName.Replace(bllPrefix, DALPrefix);//替換中級的BLL.為DAL.,就是DAL類的全名
            baseDal = Reflect<IBaseDAL<T>>.Create(this.dalName, dalAssemblyName);//構造對應的DAL數據訪問層的對象類

 

由於BLLFactory<T>通過傳入指定的業務對象,成功創建后,會返回相關聯的類的實例,因此接口的調用在設計時就知道了,也就是上面例子里面的BLLFactory<BLL.User>.Instance就是BLL.User類的實例,具有所有該類的接口方法,實現了強類型API的目的了。

下面就是該類在實際界面項目里面的使用例子代碼。

                try
                {
                    UserInfo info = BLLFactory<User>.FindByID(currentID) as UserInfo;
                    if (info != null)
                    {
                        info = SetUserInfo(info);
                        BLLFactory<User>.Instance.Update(info, info.ID.ToString());
                        RefreshTreeView();

                        MessageDxUtil.ShowTips("資料保存成功");
                    }
                }
                catch (Exception ex)
                {
                    LogTextHelper.Error(ex);
                    MessageDxUtil.ShowError(ex.Message);
                }

 

2、CallerFactory的對象統一調用規則

CallerFactory對象是用於創建基於Facade層接口的業務對象,主要用在我的WCF開發框架、混合式開發框架里面,該對象的創建邏輯類似於BLLFactory,不過它創建的對象,可能是基於WCF客戶代理的對象,也可能是對BLLFactory創建對象的進一步封裝,以便實現宏觀上的統一。如下圖所示,CallerFactory處在下面框架結構圖的中間部分,UI層的下面。

CallerFactory的調用代碼例子如下所示。

                {
                    UserInfo info = CallerFactory<IUserService>.Instance.FindByID(currentID);
                    if (info != null)
                    {
                        info = SetUserInfo(info);
                        CallerFactory<IUserService>.Instance.Update(info, info.ID.ToString());
                        RefreshTreeView();

                        MessageDxUtil.ShowTips("資料保存成功");
                    }
                }
                catch (Exception ex)
                {
                    LogHelper.Error(ex);
                    MessageDxUtil.ShowError(ex.Message);
                }

我們看到,雖然上面的代碼是基於WCF的分布式應用,我們還是可以看到,這個調用的思路和方式,和傳統Winform的BLLFactory如出一轍,能解決對象調用問題的同時,這樣的操作方式,能夠給我們學習框架提供了更好的統一模式,順利切換,而且,從傳統Winfrom開發框架的界面代碼遷移到分布式應用的WCF開發上,界面代碼的變化也是很有規律的,這就是統一模式的力量和奧妙所在。

和BLLFactory里面傳入的業務層對象不同,這里CallerFactory里面傳入的對象是Facade層的接口,那么它是如何知道我們要創建的對象,並把它轉換為我們需要的接口的呢?

    /// <summary>
    /// 混合式框架或WCF框架中針對不同調用方式的工廠類(WCF或者Win調用)
    /// </summary>
    /// <typeparam name="T">接口類型</typeparam>
    public class CallerFactory<T>
    {
        private static Hashtable objCache = new Hashtable();
        private static object syncRoot = new Object();
        private static string callerNamespace = null;//Facade接口實現類的命名空間

        /// <summary>
        /// 創建或者從緩存中獲取對應接口的實例
        /// </summary>
        public static T Instance
        {
            get
            {
                string CacheKey = typeof(T).FullName;
                T bll = (T)objCache[CacheKey];  //從緩存讀取  
                if (bll == null)
                {
                    lock (syncRoot)
                    {
                        if (bll == null)
                        {
                            bll = CreateObject(); //反射創建,並緩存
                            if (bll != null)
                            {
                                objCache.Add(typeof(T).FullName, bll); //緩存BLL業務對象
                            }
                        }
                    }
                }
                return bll;
            }
        }

從上面的代碼我們看到,這里的創建邏輯和BLLFactory很大程度的相同,只是細節部分,我使用了CreateObject 進行了隔離,放到獨立的函數里面進行創建了。

CreateObject 函數主要邏輯就是根據WCF框架配置信息,到具體的程序集里面創建對應的對象實例,然后轉換為Facade層接口,方便統一調用。這就是我WCF開發框架和混合式開發框架,統一調用接口進行通訊獲取或提交數據的工作模式。

 

以上就是我Winform開發框架、WCF開發框架、混合式開發框架、Web開發框架里面所用到的兩種方式的對象創建方式的說明,希望您能從統一的調用方式可以看到更多的奧妙及好處。

關於以上幾種框架的定義說明,請查看下面圖示的介紹,打開圖示可以查看更多的框架介紹內容。


免責聲明!

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



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