如何创建一个公共子类来删除重复代码

本文关键字:删除 子类 代码 一个 何创建 创建 | 更新日期: 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*类有一些额外的属性,这恰好是相同的。

正如其他人所建议的那样,实现这一点的最简单方法是通过多重继承。在您的具体示例中,这将意味着创建一个(可能是抽象的)类来描述MyDropDownListMyCheckBox之间的共享属性,然后让这两个类从各自的System.Web.UI.WebControls基以及这个"共享"类继承。然而,如前所述,c#不支持多重继承。来自Chris Brumme的链接:

真正适合MI的地方实际上是非常少的。在许多情况下,多接口继承可以完成这项工作。在其他情况下,您可以使用封装和委托。

您可能也考虑过使用接口。您可能已经发现,对于您的解决方案来说,这将是一个不合适的选择,因为一个接口只允许您定义类中的某些属性和方法,而不允许您定义属性或方法的定义方式。所以,这是一个不合适的选择来删除重复的代码。

这对你意味着什么?好吧,如果你想写一个同时支持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继承,你就完成了。但是,这是不可能的。

那么我们如何实现你的目标呢?这有点复杂,但是您可以在每个自定义类中封装共享属性和方法。下面是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();
    }
}

以这种方式设计的类,虽然有点复杂,但应该完成您所寻找的类型语法。

最后,我强烈建议您至少考虑重新检查您的设计,看看是否有更好的方法来处理类层次结构。我的建议是,如果您的共享属性可以作为一个逻辑实体独立存在,那么它们可能应该是它们自己的类。如果是这样,那么这个类可能是MyDropDownListMyCheckBox类的合法和合乎逻辑的成员。这意味着您的应该使用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();
        }
    }