Как проверить тип списка, если используется наследование - PullRequest
1 голос
/ 29 марта 2012

В настоящее время я работаю над программой на C #, которая создает список объекта Task, объект Task является базовым классом и многие другие наследуются от него. Я хочу сравнить тип одного из объектов в указанном списке, чтобы увидеть, какую форму следует открыть, чтобы отредактировать.

Это код, который я уже создал.

private void itemEdit_Click(object sender, EventArgs e)
    {
        int edi = taskNameBox.SelectedIndex;
        Task checkTask = todoList.ElementAt(edi);

        if(checkTask.GetType is Note)
        {
            noteBuilder editNote = new noteBuilder(todoList);
            editNote.Show();
        }

        else if(checkTask.GetType is extendedTask)
        {
            extendedTaskBuilder editTask = new extendedTaskBuilder(todoList);
            editTask.Show();
        }

        else if(checkTask.GetType is Reminder)
        {
            reminderBuilder editReminder = new reminderBuilder(todoList);
            editReminder.Show();
        }

        else if (checkTask.GetType is Appointment)
        {
            appointmentBuilder editAppointment = new appointmentBuilder(todoList);
            editAppointment.Show();
        }
    }

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

Большое спасибо

Ответы [ 5 ]

1 голос
/ 29 марта 2012

Код, подобный этому, сложно поддерживать, вам, вероятно, лучше абстрагировать его, например, так (при условии, что Task не входит в .net):

public interface IBuilder
{
     void Show();
}

public abstract class Task
{
    // ...
    public abstract IBuilder GetBuilder(TaskList todoList);
    // ...
}

public class Note : Task
{
    public override IBuilder GetBuilder(TaskList todoList)
    {
        return new noteBuilder(todoList);
    }
    // ...
}

// etc.

private void itemEdit_Click(object sender, EventArgs e)
{
    int edi = taskNameBox.SelectedIndex;
    Task checkTask = todoList.ElementAt(edi);

    IBuilder builder = checkTask.GetBuilder(todoList);
    builder.Show();
}

Альтернативно, вы можете использовать схему впрыска:

public abstract class Task
{
    protected Task(Func<TaskList, IBuilder> builderStrategy)
    {
        _builderStrategy = builderStrategy;
    }

    public IBuilder GetBuilder(TaskList todoList))
    {
        return _builderStrategy(todolist);
    }
}

public class Note : Task
{
    public Note(Func<TaskList, IBuilder> builderStrategy) : base(builderStrategy) {}
}

// ...
note = new Note(x => return new noteBuilder(x));
1 голос
/ 29 марта 2012

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

Что касается вашего размещенного кода, вероятно, было бы лучше превратить это в шаблон стратегии подход, при котором все формы наследуются от базового класса / интерфейса, который имеет метод Show.Тогда все, что вам нужно сделать, это позвонить checkTask.Show(todoList);.Если вы не хотите, чтобы это исходило от Task, тогда все ваши формы могут наследоваться от вышеуказанной базы, и вы можете использовать фабричный шаблон , который принимает Task и list ивозвращает соответствующую форму, в которой вы просто позвоните form.Show();

1 голос
/ 29 марта 2012

Рассматривали ли вы создание базового класса для всех типов, между которыми вы сейчас переключаетесь, и вызов виртуального (абстрактного) метода?

Теперь поместите весь код в if в переопределенном абстрактном методе.1004 * Преимущества: - интеллект коммутатора находится в пределах классов, к которым он принадлежит.- При добавлении нового типа вы получаете ошибку компилятора, которая также добавляет эту функцию к новому типу.

1 голос
/ 29 марта 2012

Я предлагаю вместо того, чтобы выполнять эту серию предложений «если», вы используете наследование для достижения того, что вам нужно. Сначала вы создаете виртуальный метод в вашем базовом классе. Виртуальный метод означает, что у него не будет никакой реализации в базовом классе, только объявление:

public class Task
{
    (...)
    public virtual void ShowEditForm(IList todoList);
    (...)
}

Затем вы создаете методы дочернего класса (я предполагаю, что объект todoList является IList, но просто измените его, если это не так).

public class Note: Task
{
    (...)
    public override void ShowEditForm(IList todoList)
    {
        (new noteBuilder(taskToEdit)).Show();
    }
    (...)
}

public class Reminder: Task
{
    (...)
    public override void ShowEditForm(IList todoList)
    {
        (new reminderBuilder(taskToEdit)).Show();
    }
    (...)
}

Я не писал все классы, но думаю, у вас есть идея. Чтобы вызвать метод, просто вызовите метод из класса Task, и будет выполнен правильный метод:

int edi = taskNameBox.SelectedIndex;
Task checkTask = todoList.ElementAt(edi);
checkTask.ShowEditForm(todoList);

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

Еще одна вещь, ключевое слово override в объявлении дочернего метода важно, потому что оно говорит компилятору, что этот метод следует вызывать, даже если вы вызываете его из BaseClass.

1 голос
/ 29 марта 2012

Вы пробовали проверить так:

if (checkTask is Note)
{

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