Как получить значение из System.Web.UI.Control (базовый класс)?

Есть ли способ получить доступ к значению / тексту элемента управления с помощью базового класса?

Рассматривая TextBox и HiddenField, System.Web.UI.Control является наиболее конкретным базовым классом, который они разделяют. Похоже, хороший кандидат, но я не вижу очевидного способа получить доступ к тексту / значению.

Я вижу, что оба определения класса используют ControlValuePropertyAttribute для идентификации свойства, которое содержит их текст / значение... например, HiddenField установлен в "Значение", TextBox в "Текст". Не уверен, как использовать эту информацию для получения данных, хотя.

Фон

У меня есть метод расширения, который берет текст некоторого веб-элемента управления (например, TextBox) и преобразует его в данный тип:

<Extension()> _
Public Function GetTextValue(Of resultType)(ByVal textControl As ITextControl, ByVal defaultValue As resultType) As resultType
    Return ConvertValue(Of resultType)(textControl .Text, defaultValue)
End Function

Теперь мне нужно значение HiddenField (которое не реализует интерфейс ITextControl). Было бы достаточно просто перегрузить функцию, но было бы здорово просто обработать базовый класс и больше не иметь дело с перегрузками записи.

Редактировать - дополнительная информация

Вот пример того, как используется метод расширения

Dim myThing as Decimal = tbSomeWebControl.GetTextValue(Of Decimal)(0)  ' Converts the textbox data to a decimal
Dim yourThang as Date = hdnSomeSecret.GetTextValue(Of Date)(Date.MinValue)  ' Converts the hiddenfield data to a Date

В настоящее время это требует двух перегрузок, поскольку доступ к данным осуществляется с помощью свойства Value в hiddenfields и свойства Text в текстовых полях.

Что не так с перегрузками? Ничего, кроме того, что я пишу почти один и тот же код снова и снова (просто изменяю 1-й параметр определения и 1-й аргумент его вызова).

2 ответа

Решение

Вы не можете использовать объектно-ориентированный подход для получения значения, потому что у них нет общего предка в дереве наследования, из которого вы можете извлекать данные. Решения настолько не элегантны, что вы должны просто пройти WebControl и проверить тип динамически.

Простите мой C#:

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


Решение 1. Получите данные напрямую из запроса

Недостаток: не очень ASP.NET-иш. Делает работу однако.

public string GetTextValue<ResultType>(WebControl control, ResultType defaultValue)
{
    // If you only wish data from form, and not questy string or cookies
    // use Request.Form[control.UniqueId] instead
    string value = Request[control.UniqueId];
    return ConvertValue<ResultType>(value, defaultValue);
}

Решение 2. Проверьте тип динамически

Недостаток: вы должны обеспечить обработку для нескольких типов элементов управления

public string GetTextValue<ResultType>(WebControl control, ResultType defaultValue)
{
    if (control is ITextControl)
        return ConvertValue<ResultType>((ITextControl)control.Text, defaultValue);
    else if (control is HiddenField)
        return ConvertValue<ResultType>((HiddenField)control.Value, defaultValue);
    else if (anothertype)
        return ConvertValue<ResultType>(another_retrieval_method, defaultValue);
}

Решение 3. Используйте рефлексию

Недостаток: отражение может быть сложным, не выглядит элегантно и может быть медленным на многих вызовах

public string GetTextValue<ResultType>(WebControl control, ResultType defaultValue)
{
    // Get actual control type
    Type controlType = control.GetType();
    // Get the attribute which gives away value property
    Attribute attr = controlType.GetCustomAttribute<ControlValuePropertyAttribute>();
    if (attr == null)
        throw new InvalidOperationException("Control must be decorated with ControlValuePropertyAttribute");
    ControlValuePropertyAttribute valueAttr = (ControlValuePropertyAttribute)attr;
    // Get property name holding the value
    string propertyName = valueAttr.Name;
    // Get PropertyInfo describing the property
    PropertyInfo propertyInfo = controlType.GetProperty(propertyName);
    // Get actual value from the control object
    object val = propertyInfo.GetValue(control);
    if (val == null)
        val = "";

    return ConvertValue<ResultType>(val, defaultValue);
}

Я думаю, DataItemContainer будет самой близкой вещью, которую вы ищете.

Другие вопросы по тегам