2011-09-28 67 views
5

我有兩個類從CheckBoxList派生和第二個從DropDownList。裏面的代碼是完全一樣的。唯一的區別是我需要第一個顯示checkboxlist的地方,第二個顯示dropdownlist。下面是我的代碼:如何使共同的子類刪除重複的代碼

using System; 
using System.Collections.ObjectModel; 
using System.Web.UI.WebControls; 

    namespace Sample 
    { 
     public class MyCheckBoxList : CheckBoxList 
     { 
      public int A { get; set; } 
      public int B { get; set; } 
      protected override void OnLoad(EventArgs e) 
      { 
       //dummy task 
       Collection<int> ints = new Collection<int>(); 
       //........ 
       this.DataSource = ints; 
       this.DataBind(); 
      } 
     } 
    } 

第二個

using System; 
using System.Collections.ObjectModel; 
using System.Web.UI.WebControls; 

namespace Sample 
{ 
    public class MyDropDownList : DropDownList 
    { 
     public int A { get; set; } 
     public int B { get; set; } 
     protected override void OnLoad(EventArgs e) 
     { 
      //dummy task 
      Collection<int> ints = new Collection<int>(); 
      //........ 
      this.DataSource = ints; 
      this.DataBind(); 
     } 
    } 
} 

現在你可以看到內部的代碼正好是我想要避免一樣。我如何爲它創建一個通用的類來消除代碼重複?

+3

+1努力減少代碼冗餘。雖然你的問題可能更適合這裏:http://codereview.stackexchange.com/ –

+0

@KileyNaro:很酷的瞭解codereview,不知道它存在。不要認爲它與SO不匹配。我認爲很好的問題。 +1 –

回答

3

您可以創建一個三等

public class Entity 
{ 
    public int A { get; set; } 
    public int B { get; set; } 
    Collection<int> GetCollection() 
    { 
     //dummy task 
     Collection<int> ints = new Collection<int>(); 
     //........ 
     return ints; 
    } 
} 

,然後用它在其他類別

public class MyDropDownList : DropDownList 
{ 
    public MyDropDownList() { Entity = new Entity(); } 

    public Entity {get;set;} 
    protected override void OnLoad(EventArgs e) 
    { 
     this.DataSource = Entity.GetCollection(); 
     this.DataBind(); 
    } 
} 
+0

但這導致獲取我的屬性,如Entity.A和Entity.B。我想避免這種情況。我想直接從我的aspx頁面的屬性。 –

+0

@Rocky:封裝實體,將其設爲私人並在您的課堂上創建一個屬性以訪問它。 – Arjang

+0

+1使用組合,剩下的唯一東西是讓Entity內部使用封裝,所以外部使用它不是必需的 – Arjang

0

你不能,因爲C#不支持實現的多重繼承(和你已經繼承)。你可以將一些代碼重構成第三類,並讓你的每個類都有一個實例並委託對它的調用。

你可以嘗試這樣的:http://www.codeproject.com/KB/architecture/smip.aspx,但它看起來像很多工作。

+0

僅僅因爲我很好奇並且真的不知道,您是否介意闡述如何使用代表來實現OP在找什麼? –

+1

我只是想將調用委託給第三個對象。我不是指c#的代表。 –

+0

感謝您的澄清。我明白你的意思! –

0

你用的組合物,使未涉及到這兩個類另一個類,然後有一個共同的代碼,當你需要使用的代碼在你做出一個實例或者類,你也可以用它thorugh一個界面。不需要使用繼承。

更新:下面的代碼(修改已經由meziantou提供的代碼)

internal interface IEntity 
    { 
     int A { get; set; } 
     int B { get; set; } 
     Collection<int> GetCollection { get; } 
    } 

    internal class Entity : TrialBalanceHTMLToDataTable.TrialBalance.IEntity 
    { 
     public int A { get; set; } 
     public int B { get; set; } 
     public Collection<int> GetCollection 
     { 
      get{ 
      //dummy task 
      Collection<int> ints = new Collection<int>(); 
      //........ 
      return ints; 
      } 
     } 
    } 


    public class MyDropDownList : DropDownList 
    { 
     public MyDropDownList() { _Entity = new Entity(); } 

     private IEntity _Entity { get; set; } 
     protected override void OnLoad(EventArgs e) 
     { 
      this.DataSource = _Entity.GetCollection; 
      this.DataBind(); 
     } 
    } 
+1

-1說一個界面就能解決問題;定義將在實現接口的兩個類之間重複。但是,如果您認爲通用代碼被移到另一個班級,您就可以得到+1 ......所以您甚至可以休息! –

+0

@KileyNaro:LOL :),接口不解決問題,它們只是讓你統一它們! – Arjang

+0

@KileyNaro:不!普通類將實現接口,其他兩個類將只使用它來與實現它的類進行通信,這個想法不是暗示兩個不同類中的接口 – Arjang

0

這似乎是你所要完成的是有一個類,即MyDropDownList,能夠繼承性DropDownList,並讓MyCheckBox類繼承CheckBox類的屬性,同時讓您的兩個My *類具有一些額外的屬性,這些屬性恰好相同。

正如其他人所說,最簡單的方法是通過Multiple Inheritance。在您的例子而言,這將意味着創建一個(可能abstract)類描述MyDropDownListMyCheckBox之間的共享屬性,然後讓這兩個類都從各自System.Web.UI.WebControls基地繼承以及這種「共享「班。然而,正如有人說,C# doesn't support multiple inheritance.從克里斯Brumme通過該鏈接:

的地方MI是真正合適的數量實際上是相當小的。在很多情況下,多接口繼承可以完成工作。在其他情況下,您可能能夠使用封裝和委派。

您可能也已考慮使用Interfaces。這一點,因爲你可能已經發現,將是您的解決方案的選擇不當作爲接口只允許您定義,有一類特定的屬性和方法,而不是如何屬性或方法的定義。再說一遍,這是刪除重複代碼的不恰當選擇。

這對你意味着什麼?那麼,如果你想寫一個支持myCustomDDLInstance.SelectedIndexmyCustomDDLInstance.A語法的MyDropDownList類,你將不得不做一點「魔術」。 但是,您的語言不支持您正在嘗試做的事實應該會引發紅旗!這不一定是錯誤的,但它應該是一個強有力的指標,您可能需要重新檢查您的設計。

我的猜測是這兩個類的重複部分可以獨立存在,因爲它是自己的邏輯實體。這意味着你可以合理地創建自己的類來保存這些共享屬性和方法。下面是我們得到:

SampleControl.cs

public class SampleControl 
{ 
    public int A { get; set; } 
    public int B { get; set; } 

    public Collection<int> MysteryCollection 
    { 
     get 
     { 
      Collection<int> ints = new Collection<int>(); 
      //........ 
      return ints; 
     } 
    } 
} 

如果CSHARP做的,其實支持多重繼承,你MyDropDownList類可以從兩個DropDownListSampleControl繼承和你做。但是,再次,這是不可能的。

那麼我們如何實現您的目標?這有點複雜,但是您可以在每個自定義類中共享屬性和方法Encapsulate。下面是MyCheckBoxList將是相同的,只是改變了類名MyDropDownList類(提示舉例:

public class MyDropDownList : DropDownList 
{ 
    private SampleControl mySampleControl { get; set; } 

    public int A 
    { 
     get 
     { 
      return mySampleControl.A; 
     } 

     set 
     { 
      mySampleControl.A = value; 
     } 
    } 

    public int B 
    { 
     get 
     { 
      return mySampleControl.B; 
     } 

     set 
     { 
      mySampleControl.B = value; 
     } 
    } 

    public MyDropDownList() 
    { 
     mySampleControl = new SampleControl(); 
    } 

    protected override void OnLoad(EventArgs e) 
    { 
     //dummy task 
     this.DataSource = mySampleControl.MysteryCollection; 
     this.DataBind(); 
    } 
} 

以這種方式設計,A級,而有點令人費解,要做到,你正在尋找的類型語法對。

最後一點我會強烈建議您在至少考慮重新審視你的設計,看是否有你實現你的類層次結構更好的方法。我的建議是,如果您的共享屬性可以作爲一個邏輯實體自己存在,他們可能應該是他們自己的階級。如果是這樣,那個階級是可能的您是MyDropDownListMyCheckBox類的合法邏輯成員。這意味着你應該使用myDropDownListInstance.SharedAttributesClassName.A語法。它更明確,更誠實。

+0

這是作曲,http://en.wikipedia.org/wiki/Composition_over_inheritance – Arjang