2012-01-20 55 views
1

我有一個抽象基類和兩個派生類。基類包含6個屬性,所有這些屬性都可以在表單上維護。處理同一表單中多個對象類型的好方法是什麼?

這兩個派生類都有一個額外的屬性。這兩個屬性也可以保持在相同的形式。

在我的表單中我有現在這樣的代碼:

btnSomething.visible = (myObject is DerivedA); 
    pnlPanel.visible = !(myObject is DerivedA); 

    if(myObject is DerivedA) 
    myBindingSource.DataSource = myObject as DerivedA 

    mySecondBindingSource = myObject; 

我不是很樂意使用這種方法,它的氣味。所以我的問題是,做出這個更多OO的方法是什麼?因爲它可能是,在未來DerivedC進來......

我認爲這種做法打破了OCP原則(也可能是其他的原則)

回答

2

您可以使用多態和繼承的位置:

定義一個接口

interface ICommonFeatures 
{ 
    bool ContainsFoo {get;} 
    //yak-yak 
} 

那麼你的派生類實現它

class DerivedA: ICommonFeatures 
{ 
    bool ContainsFoo {get {return true;}} 
    //so-and-so 
} 
class DerivedB: ICommonFeatures 
{ 
    bool ContainsFoo {get {return false;}} 
    //this-and-that 
} 

而當你使用它,你將只處理接口

ICommonFeatures foo = new DerivedB(); 

btnSomething.visible = foo.ContainsFoo; 
pnlPanel.visible = foo.Prop2; 
myBindingSource.DataSource = foo.CurrentDataSource 
+0

我在這個方向思考,但在你的情況,我可以閱讀'foo.Prop1'爲'foo.ShowButtonSomething'?所以基本上,每個依賴於Derived類的GUI控件都創建了一個布爾屬性? – Martijn

+0

是的,但在界面上,你應該把邏輯負載,而不是UI。所以'ShowButtonSomething' =>'ContainsFoo'。然後在你的邏輯更深處,你檢查如果這個類包含foo,那麼你想顯示一個按鈕。這種方法會將邏輯封裝在類中,並將表示與模型分離(這總是一個好主意)。另一件事是你的GUI控件應該取決於抽象接口或抽象類,如果你願意的話。 – oleksii

+0

我想我明白了,所以在'ICommonFeatures'中我可以有一個屬性,如'bool ContainsCompanyAddress',在我的表單中我設置了'txtCompanyAddress.visible = foo.ContainsCompanyAddress'? – Martijn

0

一個瘋狂的想法是讓UI擴展。 您可以使窗體實現一個基本窗體。

然後在派生表單類中,您只會爲其模型類插入缺少的控件和行爲。 在派生的模型類或庫中,您可以將某種排序綁定到正確的表單。

一個好的方法是按照一些MVP原則。

希望它可以幫助你以某種方式..

+0

我的確做了這樣的實現,但在我的解決方案中,我有不同的庫實現一組接口和基類,每個庫可以從主配置表單中選擇派生。然後在主應用程序中,我將顯示默認窗體或由庫實現的自定義窗體。 –

0

我將宣佈一個抽象的布爾方法/屬性爲每個需要根據底層類型的行爲控制。

例如

// to handle pnlPanel.visible = !(myObject is DerivedA);  
abstract bool SupportsPanel{get;} 

至於你的綁定源,我也將提供一些虛擬BindingSourceSecondBindingSource性能。

也許像(純粹的例子)

public abstract class BaseClass 
{ 
    // All your exising class declaration here 

    public virtual object BindingSource 
    { 
     get 
     { 
      // By default, a BaseClass is not valid as a binding source 
      return null; 
     } 
    } 

    public virtual object SecondBindingSource 
    { 
     get 
     { 
      // By default, a BaseClass is a valid Second Binding source 
      return this; 
     } 
    } 
} 

public class DerivedA : BaseClass 
{ 
    // All your exising class implementation here 

    public override object BindingSource 
    { 
     get 
     { 
      // For DerivedA, the data sourse is itself. 
      // other classes might have their own implementations. 
      return this; 
     } 
    } 

    // No need to override SecondBindingSource as the BaseClass one works as expected. 

} 

所以,你的代碼可能會停止關心的對象類型,如下所示:

myBindingSource.DataSource = myObject.BindingSource; 
mySecondBindingSource = myObject.SecondBindingSource; 

希望這有助於。

+0

您能否提供一個關於如何處理綁定資源的(虛擬)示例? – Martijn

+0

@Martijn我已經爲你更新了我的文章。它與開始時我的想法略有不同,但想法是一樣的:只用你的對象作爲'BaseClass'並封裝派生類中的特定內容。 – remio

相關問題