2010-01-15 35 views
1

假定具有信用卡類的訂單(集合類)作爲屬性。根據訂單的狀態,我想更改信用卡類屬性的訪問修飾符。例如:如果Order state = Order.NewOrder,則允許信用卡屬性可修改,但是如果Order state = Order.CompletedOrder,我不想讓信用卡中的屬性可以設置。取決於狀態的C#訪問修飾符

我希望能夠在編譯時和運行時檢查。

我想到的唯一解決方案是創建2個繼承自同一父類的類;一個允許屬性可以被設置爲另一個不能,但如果有一個狀態需要一些屬性可設置而其他屬性不可用,則它會非常快速地變得毛茸茸的。

任何想法,不勝感激。

+1

您如何設想編譯時解決這個工作? – jason 2010-01-15 02:13:31

+0

他會寫他自己的VS擴展。 – ChaosPandion 2010-01-15 02:48:48

+0

是的,創建2靜態類是如何實現編譯時檢查。不過,我仍然有一個類,並拋出運行時'OperationNotAllowed'類錯誤;你會複製一個類型的代碼/同步/維護2個類。 – Gishu 2010-01-15 02:53:52

回答

2

另一種方式來解決這個問題是在「設計模式」 pg.208-209爲保護代理

Proxy pattern「爲另一個對象提供代理或佔位符來控制對其的訪問。」您將對象的保護代理版本替換爲保護代理中的實際對象和訪問邏輯,以返回只讀數據,但會檢查何時嘗試寫入。

+0

您希望編譯時檢查vs運行時檢查的原因是您不希望開發人員使用您的業務對象來執行一個集合,即Order.CreditCard.Number = ...然後發現他們可以'當拋出異常時。對象應始終設計爲使開發人員無需知道運行IsChangeAllowed()等。 – traderde 2010-01-15 04:27:38

+0

「對象應始終設計爲使開發人員無需知道運行IsChangeAllowed()」 - 這取決於您嘗試的內容創建。我並不是想暗示開發者需要運行支票,我只是想了解你的問題。 – 2010-01-15 06:21:05

+0

這個解決方案的問題是,如果IsWritable = false,該設置將運行,並且用戶不會直觀地知道它爲什麼沒有正確設置。 – traderde 2010-01-15 06:50:08

3

我會用兩個不同的接口來表示信用卡對象。一個人可能會有制定者和另一個獲得者。 Order類中的CreditCard屬性只能是getter接口。

class CreditCardBase : ICreditCard 
{ 
    string Name { get; } 
} 

interface IWritableCreditCard : ICreditCard 
{ 
    string Name { get; set; } 
} 

class WritableCreditCard : CreditCardBase, IWritableCreditCard {} 

class Order 
{ 
    private ICreditCard _card = new WritableCreditCard(); //initially... 
    public ICreditCard Card { get {return _card; } } 

    void OnComplete(...) { _card = new CreditCardBase(copy from _card); } 
} 

在運行時投「一卡通」的屬性的setter界面修改該卡的性能。如果訂單狀態現在處於只讀狀態,那麼實現CreditCard的對象將被換出只有實現getter的實現。

我看不出你如何能在編譯時區分,但至少正常行動將是安全的「吸氣劑只是」呼籲和修改代碼將是一個)醜且易於檢測和b)將如果在錯誤的時間執行,則返回null或拋出。

+0

這是一個類似的想法,除了我將只使用一個只有getter的類以及所有支持字段是隻讀的,因此屬性只能在實例化時設置。如果需要更改,我會創建一個新實例,將所有現有屬性+更改複製到新實例中。 – traderde 2010-01-15 04:20:50

+0

@Daver:不要假設你可以用你代表'WritableCreditCard'類的方式更新你的例子嗎?我無法想象你會怎麼做,因爲'new'會應用於繼承的屬性'get',但是沒有'set'會被設置爲'new'。當重寫訪問器時,使其成爲'虛擬'也會失敗。 – Codesleuth 2010-01-21 15:50:31