Приведение объекта-отправителя в обработчик событий с использованием GetType (). Name

StackOverflow https://stackoverflow.com/questions/634112

  •  10-07-2019
  •  | 
  •  

Вопрос

У меня есть обработчик событий для текстового поля, а также для RichTextBox. Код идентичен, но

В обработчике # 1 я делаю:

RichTextBox tb = (RichTextBox)sender

В обработчике # 2 соответственно:

TextBox tb = (TextBox)sender

Таким образом, я могу полностью управлять элементом управления отправкой. Я хочу знать, как я могу привести отправляющий объект к Textbox или RichTextbox в соответствии с его типом, используя

sender.GetType().Name

, а затем создайте элемент управления во время выполнения и работайте с ним. Таким образом, мне нужна только одна функция обработчика событий: меньше кода, меньше ошибок, проще в обслуживании и СУХОЙ: -)

Это было полезно?

Решение

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

Другие советы

Тебе никогда не придется кастовать. Когда я начинал, я думал так же, этот «шаблон» неверен и не совсем логичен.

Лучше всего использовать что-то вроде:

if (sender is TextBox)
{
  TextBox tb = (TextBox)sender;
}
else if (sender is RichTextBox)
{
  RichTextBox rtb = (RichTextBox)sender;
}
else
{
  // etc
}

Я знаю, что это очень старая запись, но в Framework 4 вы можете использовать отправителя в качестве элемента управления:

Control cntrl = (Control)sender;
cntrl.Text = "This is a " + sender.GetType().ToString();

Обратите внимание, что вы можете ссылаться только на элементы управления, общие для всех различных элементов управления (т. е. на текст).

RichTextBox textbox = sender as RichTextBox;
if (textbox != null)
{
   // do stuff as a rtb
   textbox.Text = "I'm a rtb";
   return;
}

TextBox textbox = sender as TextBox;
if (textbox != null)
{
   // do stuff as a textbox
   textbox.Text = "I'm a textbox";
}

Приведение может быть выполнено только во время компиляции, и поэтому вам нужно знать типы, к которым вы хотите привести во время компиляции. Поэтому тип времени выполнения (возвращаемый GetType ()) нельзя использовать при приведении.

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

Если вы хотите строгую типизацию, единственный базовый класс или интерфейс для двух отправителей - единственный путь.

Вместо имени типа вы можете использовать ' является .

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

if (sender is RichTextBox)
{
    // ...
}
else if (sender is TextBox)
{
    // ...
}

Однако вы обычно хотите, чтобы объект: C # 7 имеет приятный синтаксис, который позволяет вам тестировать и получать встроенное значение:

if (sender is RichTextBox richTextBox)
{
    richTextBox.Text = "I am rich";
}
else if (sender is TextBox textBox)
{
    textBox.Text = "I am not rich";
}

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

if (sender is RichTextBox tb)
{
    // ... //
} 
else if (sender is TextBox tb)
{
    // ... //
}

Если код идентичен, вам нужно заботиться? Интересно, если приведение к Control не даст вам все, что вам нужно ...

Один сложный обработчик не обязательно лучше, чем несколько простых обработчиков. В любом случае, если вы должны пойти по этому пути, «as» будет «" предпочтительнее (не зависит от строк и т. д.):

TextBox tb = sender as TextBox;
if(tb!=null) {/* TextBox specific code */}
...

если вы не хотите повторять код, тогда вы можете привести оба элемента управления, рефакторинг общих действий в отдельный метод, который принимает TextBoxBase в качестве аргумента. А в ваших обработчиках событий преобразуйте элементы управления в System.Windows.Forms.TextBoxBase, так как оба элемента управления получены из TexbBoxBase и вызывают метод.

Обратите внимание: если вам нужны конкретные свойства любого из этих элементов управления, этот рефакторинг не сработает.

Общая версия приведенного выше кода:

public static void CastAndUse<T>(object item, Action<T> action) where T : class
{
    T thing = item as T;

    if (thing != null)
    {
        action(thing);
    }
}

Используется как:

CastAndUse(sender, new Action((foo) => foo = bar));

Не идеально, но удобно.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top