企業管理軟體開發架構之三 系統分層組織圖

來源:互聯網
上載者:User
文章目錄
  • Business Logic 業務實體層
  • 介面和邏輯分離
  • Interface/Implementation 介面層和介面實現層

我給MIS類型的軟體分四個實現層次,三層架構。

BusinessLogic 業務實體 由LLBL Gen 產生業務實體,代碼產生器產生

Interface 資料提供者 根據實體產生的資料提供者,由Code Smith產生

Manager 介面實現 根據實體產生的資料提供者的實現代碼,由Code Smith產生

UI 介面層 拖拉控制項,綁定資料到介面中

 

Business Logic 業務實體層

以ORM作為資料訪問基礎技術,業務實體中包含資料之間的關係邏輯,而不再是用於填充資料的實體。

以上結構由LLBL Gen自動產生,它已經為我們產生了實體,實體驗證類型,資料提供者和相關的輔助類型。

公司註冊中的公司實體,它的定義如下代碼所示

[Serializable]public partial class CompanyEntity : CommonEntityBase        // __LLBLGENPRO_USER_CODE_REGION_START AdditionalInterfaces        // __LLBLGENPRO_USER_CODE_REGION_END    
{        #region Class Member Declarations        private EntityCollection<ModuleEntity> _modules;        // __LLBLGENPRO_USER_CODE_REGION_START PrivateMembers        // __LLBLGENPRO_USER_CODE_REGION_END        #endregion        #region Statics        private static Dictionary<string, string>    _customProperties;        private static Dictionary<string, Dictionary<string, string>>    _fieldsCustomProperties;        /// <summary>All names of fields mapped onto a relation. Usable for in-memory filtering</summary>        public static partial class MemberNames        {            /// <summary>Member name Modules</summary>            public static readonly string Modules = "Modules";        }        #endregion                /// <summary> Static CTor for setting up custom property hashtables. Is executed before the first instance of this entity class or derived classes is constructed. </summary>        static CompanyEntity()        {            SetupCustomPropertyHashtables();        }                /// <summary> CTor</summary>        public CompanyEntity():base("CompanyEntity")        {            InitClassEmpty(null, null);        }.....}

LLBL Gen設計器產生的實體代碼有幾個特點

  • 產生有多個用途的構造方法(ctor)。我們經常用到的是不帶參數的構造方法,和帶有主索引值參數的方法。
[EditorBrowsable(EditorBrowsableState.Never)]protected CompanyEntity(SerializationInfo info, StreamingContext context) : base(info, context)        {            if(SerializationHelper.Optimization != SerializationOptimization.Fast)             {                _modules = (EntityCollection<ModuleEntity>)info.GetValue("_modules", typeof(EntityCollection<ModuleEntity>));                this.FixupDeserialization(FieldInfoProviderSingleton.GetInstance());            }            // __LLBLGENPRO_USER_CODE_REGION_START DeserializationConstructor            // __LLBLGENPRO_USER_CODE_REGION_END}
 

這個構造方法用在序列化對象時發生,比如.net Remoting遠程返回對象時。

 

  • 產生包含自訂屬性的欄位 自訂屬性常用用屬性的特殊設定。比如CompanyEntity.CompanyCode,實際中為了不區分CompanyCode的大小寫,統一要求為大寫,我們可以在此添加自訂屬性RequiredCap,再到程式運行時讀取此屬性,並設定控制項的字母大小寫特性。
private static Dictionary<string, string>    _customProperties;private static Dictionary<string, Dictionary<string, string>>    _fieldsCustomProperties;private static void SetupCustomPropertyHashtables()        {            _customProperties = new Dictionary<string, string>();            _fieldsCustomProperties = new Dictionary<string, Dictionary<string, string>>();            Dictionary<string, string> fieldHashtable;            fieldHashtable = new Dictionary<string, string>();            _fieldsCustomProperties.Add("CompanyCode", fieldHashtable);......Dictionary<string, string> fieldCustomProperties = CompanyEntity.FieldsCustomProperties["CompanyCode"];string requiredCap = fieldCustomProperties["RequiredCap"];

讀取自訂屬性RequiredCap的值為true時,設定控制項的CharachterCasing屬性。

 

介面和邏輯分離

再來看業務實體的業務計算如何發生。範例程式碼如下所示

  protected override void OnFieldValueChanged(object originalValue, IEntityField2 field)        {            base.OnFieldValueChanged(originalValue, field);            switch ((CompanyFieldIndex)field.FieldIndex)            {                case CompanyFieldIndex.DriverAssembly:                    OnChangeDriverAssembly((string)originalValue);                    break;            }        }        private void OnChangeDriverAssembly(string originalValue)        {            if (this.DriverAssembly == originalValue || String.IsNullOrEmpty(DriverAssembly)) return;            this.DriverType = BaseCommon.GetProjectName(ModuleType.BusinessLogic, DriverAssembly);        }

當我在介面中改變當前介面外掛程式程式集時,它會為我自動讀取這個程式集的類型資訊,項目命名資訊。要理解這種方式,需要先理解.NET開發中的資料繫結技術。資料來源控制項相當於一個橋樑,串連資料實體和介面控制項,當給資料來源控制項賦值時,控制項會讀取資料實體的值,當介面中的控制項值發生改變時,藉助於資料來源控制項,自動把更改後的資料回寫到資料實體中。所以,當資料實體中值發生改變後,我們可以註冊相應的改變事件,作出商務邏輯處理,資料來源控制項會讀取改變之後的資料實體值,呈現在介面上。幾乎所有的商務邏輯是依照此方式編程,也實現了介面和邏輯分離。

介面和邏輯分離後,介面中的作用就是將控制項綁定到資料來源控制項,再以Code Smith來產生資料讀寫介面:

 public override EntityBase2 LoadEntity(string refNo)        {            IItemManager manager = ClientProxyFactory.CreateProxyInstance<IItemManager>();            ItemEntity customer = manager.GetItem(refNo);            return customer;        }        public override void DeleteEntity(EntityBase2 entity)        {            ItemEntity user = (ItemEntity)entity;            IItemManager manager = ClientProxyFactory.CreateProxyInstance<IItemManager>();            manager.DeleteItem(user);        }        public override void SaveEntity(EntityBase2 entity)        {            ItemEntity user = (ItemEntity)entity;            IItemManager manager = ClientProxyFactory.CreateProxyInstance<IItemManager>();            manager.SaveItem(user);        }

系統中所有與資料庫讀寫相關的介面代碼均是以此方式實現。

 

Interface/Implementation 介面層和介面實現層

介面與它的實體均以Code Smith模板產生,效率高。如下所示的供應商介面

 public interface IVendorManager    {        VendorEntity GetVendor(System.String VendorNo);        VendorEntity GetVendor(System.String VendorNo, IPrefetchPath2 prefetchPath);        VendorEntity GetVendor(System.String VendorNo, IPrefetchPath2 prefetchPath, ExcludeIncludeFieldsList fieldList);        EntityCollection GetVendorCollection(IRelationPredicateBucket filterBucket);        EntityCollection GetVendorCollection(IRelationPredicateBucket filterBucket, ISortExpression sortExpression);        EntityCollection GetVendorCollection(IRelationPredicateBucket filterBucket, ISortExpression sortExpression, IPrefetchPath2 prefetchPath);        EntityCollection GetVendorCollection(IRelationPredicateBucket filterBucket, ISortExpression sortExpression, IPrefetchPath2 prefetchPath, ExcludeIncludeFieldsList fieldList);        VendorEntity SaveVendor(VendorEntity vendor);        VendorEntity SaveVendor(VendorEntity vendor, EntityCollection entitiesToDelete);        VendorEntity SaveVendor(VendorEntity vendor, EntityCollection entitiesToDelete, string seriesCode);        void SaveCollection(EntityCollection vendors);        void DeleteVendor(VendorEntity vendor);        bool IsVendorExist(System.String VendorNo);        bool IsVendorExist(IRelationPredicateBucket filterBucket);        int GetVendorCount(IRelationPredicateBucket filterBucket);        VendorEntity CloneVendor(System.String VendorNo);        void PostVendor(System.String VendorNo);        void PostVendor(VendorEntity vendor);        void ApprovalItem(EntityCollection vendors);    }

實現介面的Manager類型代碼例子如下

 public class VendorManager : Foundation.Common.ManagerBase, IVendorManager    {        public VendorEntity GetVendor(System.String VendorNo)        {            return GetVendor(VendorNo, null);        }        public VendorEntity GetVendor(System.String VendorNo, IPrefetchPath2 prefetchPath)        {            return GetVendor(VendorNo, prefetchPath, null);        }        public VendorEntity GetVendor(System.String VendorNo, IPrefetchPath2 prefetchPath, ExcludeIncludeFieldsList fieldList)        {            VendorEntity _Vendor = new VendorEntity(VendorNo);            using (DataAccessAdapterBase adapter = GetCompanyDataAccessAdapter())            {                bool found = adapter.FetchEntity(_Vendor, prefetchPath, null, fieldList);                if (!found) throw new Foundation.Common.RecordNotFoundException("Invalid Vendor");            }            return _Vendor;        }

介面層中或是實體層,使用下面的介面來提供者:

ICompanyManager  _companyManager = ClientProxyFactory.CreateProxyInstance<ICompanyManager>();CompanyEntity _company = _companyManager.GetCompany(“Kingston”)

如果沒有採用分布式技術(.net Remoting,WCF),CreateProxyInstance方法直接返回ICompanyManager介面的實體類型的執行個體,供介面調用。如果有應用.net Remoting技術,則先以下面的方法產生伺服器對象:用戶端產生的實體物件會是一個遠程代理,指向遠程對象:

RemotingConfiguration.RegisterActivatedServiceType(type);

介面與實現分離的好處在這裡體現的很明顯,簡單的切換部署模式(單機,分布式)不需要改變代碼。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.