Как сделать общий подкласс для удаления дублирующего кода - PullRequest
5 голосов
/ 29 сентября 2011

У меня есть два класса, один из которых получен из 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();
        }
    }
}

Теперь, как вы видите, внутренний код точно такой же, чего я хочу избежать. Как создать общий класс для устранения дублирования кода?

Ответы [ 4 ]

3 голосов
/ 29 сентября 2011

Вы можете создать третий класс

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 голосов
/ 29 сентября 2011

Может показаться, что вы пытаетесь достичь одного класса, то есть MyDropDownList, иметь возможность наследовать свойства от DropDownList и иметь класс MyCheckBox, наследующий свойства от * Класс 1004 *, в то время как два ваших класса My * имеют некоторые дополнительные свойства, которые оказываются идентичными.

Как и предполагали другие, самый простой способ сделать это - через Множественное наследование . В частности, в вашем примере это будет означать создание (возможно, abstract ) класса, который описывает общие атрибуты между MyDropDownList и MyCheckBox, и затем эти два класса наследуются от обоих их соответствующих System.Web. UI.WebControls основы, а также этот «общий» класс. Однако, как уже было сказано, C # не поддерживает множественное наследование. От Криса Брамма по этой ссылке:

Количество мест, где МИ действительно подходит, на самом деле довольно мало. Во многих случаях множественное наследование интерфейса может сделать работу вместо этого. В других случаях вы можете использовать инкапсуляцию и делегирование.

Возможно, вы также подумали об использовании Interfaces . Это, как вы, возможно, обнаружили, было бы неподходящим выбором для вашего решения, так как Интерфейс только позволяет вам определять, что в классе есть определенные свойства и методы, но не то, как определяются свойства или методы. Опять же, это неуместный выбор для удаления дубликата кода.

Что это значит для вас? Что ж, если вы хотите написать класс MyDropDownList, который поддерживает синтаксисы myCustomDDLInstance.SelectedIndex и myCustomDDLInstance.A, вам придется сделать немного "магии". Но тот факт, что ваш язык не поддерживает то, что вы пытаетесь сделать, должен поднять красный флаг! Это не обязательно неправильно, но это должен быть сильный индикатор того, что вы, возможно, захотите пересмотреть свой дизайн.

Я предполагаю, что дублирующаяся часть двух классов может стоять отдельно в качестве своей логической сущности. Это означает, что вы можете обоснованно создать свой собственный класс для хранения этих общих свойств и методов. Вот что мы получаем:

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. Это и более откровенно, и более честно.

0 голосов
/ 29 сентября 2011

Вы используете композицию, создаете другой класс, который не связан с этими двумя классами, затем имеете общий код в этом, когда вам нужно использовать код в любом из классов, которые вы создаете, вы также можете использовать его черезинтерфейс.Нет необходимости использовать наследование.

Обновление: код ниже (изменен код, уже предоставленный 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();
        }
    }
0 голосов
/ 29 сентября 2011

вы не можете, потому что c # не поддерживает множественное наследование реализации (а вы уже создаете подклассы).Вы могли бы преобразовать часть кода в третий класс, и у каждого из ваших классов был бы экземпляр и делегировать вызовы к нему.

Вы можете попробовать что-то вроде этого: http://www.codeproject.com/KB/architecture/smip.aspx,, но это выглядит какмного работы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...