Даункинг в C # - PullRequest
       84

Даункинг в C #

6 голосов
/ 15 июля 2009

Я столкнулся с проблемой, которую не знаю, как решить, и надеюсь, что сообщество может помочь.

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

Для простоты программирования (и использования) я анализирую текстовый файлв объект List и использование DataGridView для отображения интересов путем установки свойства DataSource объекта DataGridView.

Что я хочу сделать, это добавить столбец в сетку, который называется «Импорт» сфлажок, который пользователь может установить, чтобы указать, следует ли импортировать каждый вывод.

Моя первая мысль - извлечь класс из вывода: public Class LeadWithImportCheckbox : Lead { bool bImport = false;</p> <p>public bool Import { get { return bImport;} set { bImport = value;} } }

Однако механизм синтаксического анализа возвращаетсписок ведущих объектов.Я не могу уменьшить LeadWithImportCheckbox.Сбой: LeadWithImportCheckbox newLead = (LeadWithImportCheckbox)LeadFromParsingEngine; Это недопустимое приведение.

Другой вариант, который я вижу, заключается в создании конструктора для LeadWithImportCheckbox:

public LeadWithImportCheckbox(Lead newlead) { base.Property1 = newlead.Property1; base.Property2 = newlead.Property2; .... base.Property_n = newlead.Property_n; } Это проблематично по двум причинам.Во-первых, у объекта Lead есть несколько десятков свойств, и написание этого конструктора - это PITA.

Но что еще хуже, если я когда-нибудь изменю базовую структуру Lead, мне нужно помнить, чтобы вернуться и изменить этот конструктор для LeadWithImportCheckbox.Это опасно для обслуживания моего кода.

Есть ли лучший способ достичь моей цели?

Ответы [ 11 ]

7 голосов
/ 15 июля 2009

или, чтобы избежать аспекта PITA, используйте отражение ... (попробуйте это ...)

РЕДАКТИРОВАТЬ: использовать свойство, а не поле, как я изначально написал ...

public class NewLead : Lead
{
    public bool Insert;
    public NewLead(Lead lead, bool insert)
    {
        Insert = insert;
        foreach (PropertyInfo pi in typeof(Lead).GetProperties())
            GetType().GetProperty(pi.Name).SetValue
               (this, pi.GetValue(lead,null), null);
    }
}
4 голосов
/ 15 июля 2009
public class LeadListItem
{
    public Lead Lead { get; set; }
    public bool ShouldImport { get; set; }
}

т.е. не копируйте содержимое объекта Lead, просто сохраните ссылку на него в новом объекте LeadListItem, который добавляет дополнительную информацию «вне» исходного объекта.

Если вы хотите, чтобы свойства Lead появлялись в сетке, почти наверняка есть способ сделать это. Почему бы не задать этот вопрос, вместо того, чтобы понизить голос за то, что я сказал вам правильный ответ на этот вопрос!

3 голосов
/ 15 июля 2009

Пара вариантов, которые вы могли пропустить:

  • Вы можете обновить сам объект Lead, чтобы иметь свойство Import (по умолчанию false).
  • Вы могли бы сделать так, чтобы ваш объект ImportLead рассматривал Lead как полезную нагрузку (даже сделав его универсальным, если хотите), поэтому вам не нужен большой конструктор.
  • Создайте новый список или список перечисляемых объектов Lead, который содержит только те объекты, которые вы хотите импортировать.
1 голос
/ 15 июля 2009

Я видел правильное решение, перечисленное так много раз, что я чувствую себя как пята, публикуя его снова, но лучший способ подойти к этому - написать оболочку для объекта Lead, который включает флаг импорта.

Если свойства объекта Lead не отображаются в GridView из-за привязки данных к объекту, напишите промежуточные свойства, которые отражают свойства Lead объекта обертки.

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

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

1 голос
/ 15 июля 2009

Есть много способов сделать это, но «правильный» способ появляется из-за того, что вы сказали здесь:

Для простоты программирования (и использования) я Разбор текстового файла в Список объектов и использование DataGridView для отображения потенциальных клиентов установка свойства DataSource объекта DataGridView.

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

Ваш Lead объект хорошо стоит сам по себе, и вы хотите присоединить к нему некоторые метаданные - вы не хотите создавать другую Lead классификацию (т.е. класс LeadWithImportCheckbox).

Итак, лучший подход в вашем случае - иметь такой класс:

public class LeadInfo 
{
    private Lead lead;
    private bool shouldImport;

    public LeadInfo(Lead lead)
    {
        this.lead = lead;
        this.ShouldImport = false;
    }

    public bool ShouldImport 
    { 
        get { return shouldImport;  }
        set { shouldImport = value; }  
    }
}

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

1 голос
/ 15 июля 2009

Я не могу опускаться до того, что это не так. Если объект был создан как Lead, то он не может быть передан ни в один производный класс. Если он был создан как LeadWithImportCheckbox, а затем возвращен к вашему коду как Lead, то вы можете уменьшить его.

Protip: проверка типа во время выполнения с оператором is.

1 голос
/ 15 июля 2009

Вы можете только понизить, если объект, который будет понижен, действительно объект этого типа.

Более простым способом решения вашей проблемы было бы наличие класса DisplayLead, например:

  public class DisplayLead {
      Lead lead;
      bool bImport;
  }

, что также поможет вам отделить хранимые данные от их представления в графическом интерфейсе.

1 голос
/ 15 июля 2009

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

Затем обработайте все, что вы хотите сделать с вновь созданным списком.

Редактирование: при работе со списками следует соблюдать осторожность, так как каждый объект класса на самом деле является только указателем на класс, поэтому если вы работаете с исходным списком и делаете что-то вроде:

List<Lead> Importable = new List<Lead>();

for(int i=0, i++, i<viewGrid.Count)
    if(viewGrid[i].CheckedColumn.Checked)
        Importable.Add(OriginalList[i]);

Эти объекты будут существовать в обоих списках, и если вы отредактируете данные Лида в обоих списках, оба будут изменены.

0 голосов
/ 15 июля 2009

Если у вашего класса Lead есть конструктор копирования (например, «Lead (Lead otherLead)»), LeadWithImportCheckbox унаследует это, и вы можете просто вызвать базовый конструктор Lead в конструкторе LeadWithImportCheckbox - следовательно, нет необходимости в LeadWithImportCheckbox, чтобы знать о детали свинца.

0 голосов
/ 15 июля 2009

Рекомендую попробовать модифицировать (обновить) импортированные лидирующие объекты.

Попробуйте начать с примеров здесь ...

...