2013-03-30 39 views
0

我有一個數據庫,其中包含「小部件」,比方說。例如,小部件具有諸如「長度」和「寬度」等屬性。用於創建wdigets的原始低級API是一團糟,所以我正在編寫一個更高級別的函數集以使調用者更容易。數據庫很奇怪,我不能很好地控制創建widget對象的時間。具體來說,直到處理的後期階段,以及某些其他事情先發生之後才能創建。但是,我希望我的呼叫者認爲在早期階段已創建了一個窗口小部件對象,以便他們可以從一開始就獲取/設置其屬性。代理對象來模擬即將創建的數據庫

所以,我實現了一個「ProxyWidget」對象,我的呼叫者可以使用它。它具有private_Length和private_Width等私有字段,可以存儲所需的值。然後,它還具有公共屬性「長度」和「寬度」,以便我的呼叫者可以訪問。如果來電者告訴我設置Width屬性的值,該邏輯是:

  • 如果相應的控件對象在數據庫中已存在,則設置 其Width屬性
  • 如果不是,存儲給定寬度值在private_Width字段中供以後使用。

在稍後的階段,當我確信窗口小部件對象已經在數據庫中創建時,我複製所有值:從private_Width複製到數據庫寬度字段等等(一個字段/屬性不幸的是)。

這適用於一種類型的小部件。但是我有大約50種類型,每種類型都有大約20個不同的領域/屬性,這導致了難以維繫的混亂。我想知道是否有更聰明的方法。也許我可以使用反射來創建「代理」對象,並以通用的方式複製字段/屬性數據,而不是編寫大量的重複代碼?以某種方式分解通用代碼?我能從「數據綁定」模式學到什麼嗎?我是一名數學家,不是程序員,我有一種不安的感覺,我目前的方法很簡單。我的代碼是用C#編寫的。

+0

當您在數據庫中創建窗口小部件時,您有任何通知?否則,你怎麼知道你什麼時候可以保存你的緩衝變化? – stakx

+0

不是真的「通知」,但有一個功能,我可以打電話找出小部件是否存在於數據庫中,並且有一個時間點我確定它存在,甚至沒有問。在後面的時間點,我保存緩衝的數據。 – bubba

回答

1

首先,以我的經驗,手工編碼的數據訪問層可以感覺像很多重複性的工作(投入到位的ORM,如NHibernate的或實體框架,威力有所緩解這個問題),並更新舊數據訪問層糟糕的工作,特別是當它由許多部分組成時。

有些事情在你的問題中還不清楚,但我認爲仍然有可能給出一個高層次的答案。這些是爲了給你一些想法:

  • 你可以建立ProxyWidget無論是作爲Widget替代實現(或者從現有的低級API的widget類的叫法),也可以實現它「在...之上「,或作爲」包裝物「,Widget。這是Adapter design pattern

    public sealed class ExistingTerribleWidget { … } 
    
    public sealed class ShinyWidget // this is the wrapper that sits on top of the above 
    { 
        public ShinyWidget(ExistingTerribleWidget underlying) { … } 
        private ExistingTerribleWidget underlying; 
        … // perform all real work by delegating to `underlying` as appropriate 
    } 
    

    我會建議(至少同時仍存在使用現有的低級API代碼)您使用這種模式,而不是創建一個完全獨立的Widget實現,因爲如果曾經有一個數據庫模式的變化,你將不得不更新兩個不同的API。如果您將新的EasyWidget類構建爲現有API頂層的包裝,它可能保持不變,只有底層實現才需要更新。

  • 您描述ProxyWidget具有兩種功能(1)允許修改一個已經持續插件; (2)緩存一個新的小部件,稍後將添加到數據庫中。

    你可以也許簡化設計,如果你有一個共同的基本類型和兩個子類:一是對於尚未被持久然而新的部件,一個是已經持續小部件。後者可能亞型有一個附加的數據庫ID屬性,使得現有的插件可以被識別,加載,修改和更新在數據庫中:

    interface IWidget { /* define all the properties required for a widget */ } 
    
    interface IWidgetTemplate : IWidget 
    { 
        IPersistedWidget Create(); 
        bool TryLoadFrom(IWidgetRepository repository, out IPersistedWidget matching); 
    } 
    
    interface IPersistedWidget : IWidget 
    { 
        Guid Id { get; } 
        void SaveChanges(); 
    } 
    

    這是Builder design pattern一個例子。

  • 如果您需要爲許多類編寫類似的代碼(例如,您的50多個數據庫對象類型),則可以考慮使用T4 text templates。這隻會使編寫代碼的重複性降低;但你仍然需要在某個地方定義50多個對象。

+0

感謝您的想法。就像你描述的那樣,我的高級NewWidget確實是一個OldWidget的包裝。我無法更改實現OldWidget的代碼,因此無法從同一接口繼承OldWidget和NewWidget,我可以嗎?如果可以的話,這將是很好的/自然的 - 它們的屬性幾乎完全相同。 T4文本模板很有趣。我使用類似的想法來編寫原始代碼,除了我使用了Excel和宏。所以,我沒有親手寫代碼,但我仍然不自覺 - 15000行重複的喋喋不休,經常需要更新。 – bubba

+0

** 1。** T4很不錯,因爲它與Visual Studio和構建系統相集成得很好。但我不是推銷員 - 這只是一種可能性,不要盲目地遵循我的建議。 ** 2。**不,您無法將界面添加到現有類型。你只能創建一個新的包裝類型並在那裏實現接口。 – stakx