如何创建一个公共子类来删除重复代码
本文关键字:删除 子类 代码 一个 何创建 创建 | 更新日期: 2023-09-27 18:10:10
我有两个类,一个来自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();
}
}
}
现在你可以看到内部代码是完全相同的,我想避免。我如何为它创建一个公共类,以消除代码的重复?
可以创建第三个类
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();
}
}
你不能,因为c#不支持实现的多重继承(而且你已经子类化了)。您可以将一些代码重构为第三个类,并让每个类都有一个实例,并委托对它的调用。
您可以尝试这样做:http://www.codeproject.com/KB/architecture/smip.aspx,但它看起来像很多工作
看来你想要完成的是有一个单一的类,即MyDropDownList
,能够从DropDownList
继承属性,并让MyCheckBox
类从CheckBox
类继承属性,同时让你的两个My*类有一些额外的属性,这恰好是相同的。
正如其他人所建议的那样,实现这一点的最简单方法是通过多重继承。在您的具体示例中,这将意味着创建一个(可能是抽象的)类来描述MyDropDownList
和MyCheckBox
之间的共享属性,然后让这两个类从各自的System.Web.UI.WebControls基以及这个"共享"类继承。然而,如前所述,c#不支持多重继承。来自Chris Brumme的链接:
真正适合MI的地方实际上是非常少的。在许多情况下,多接口继承可以完成这项工作。在其他情况下,您可以使用封装和委托。
您可能也考虑过使用接口。您可能已经发现,对于您的解决方案来说,这将是一个不合适的选择,因为一个接口只允许您定义类中的某些属性和方法,而不允许您定义属性或方法的定义方式。所以,这是一个不合适的选择来删除重复的代码。
这对你意味着什么?好吧,如果你想写一个同时支持myCustomDDLInstance.SelectedIndex
和myCustomDDLInstance.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
类可以从DropDownList
和SampleControl
继承,你就完成了。但是,这是不可能的。
那么我们如何实现你的目标呢?这有点复杂,但是您可以在每个自定义类中封装共享属性和方法。下面是MyDropDownList
类的示例(注意MyCheckBoxList
也一样,只是更改类名):
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();
}
}
以这种方式设计的类,虽然有点复杂,但应该完成您所寻找的类型语法。
最后,我强烈建议您至少考虑重新检查您的设计,看看是否有更好的方法来处理类层次结构。我的建议是,如果您的共享属性可以作为一个逻辑实体独立存在,那么它们可能应该是它们自己的类。如果是这样,那么这个类可能是MyDropDownList
和MyCheckBox
类的合法和合乎逻辑的成员。这意味着您的应该使用myDropDownListInstance.SharedAttributesClassName.A
语法。
您使用组合,创建另一个与这两个类无关的类,然后在该类中使用通用代码,当您需要在创建实例的任何一个类中使用代码时,您也可以通过接口使用它。不需要使用inheritance
更新:以下代码(修改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();
}
}