Подтвердить что ты не робот

Объект Cast для T

Я разбираю XML файл с классом XmlReader в .NET, и я думал, что было бы разумно написать общую функцию синтаксического анализа, чтобы в целом читать разные атрибуты. Я придумал следующую функцию:

private static T ReadData<T>(XmlReader reader, string value)
{
    reader.MoveToAttribute(value);
    object readData = reader.ReadContentAsObject();
    return (T)readData;
}

Как я понял, это не работает полностью, как я планировал; он выдает ошибку с примитивными типами, такими как int или double, так как приведение не может преобразовать из string в числовой тип. Есть ли способ, чтобы моя функция преобладала в измененной форме?

4b9b3361

Ответ 1

Сначала проверьте, можно ли его отличить.

if (readData is T) {
    return (T)readData;
} else {
    try {
       return (T)Convert.ChangeType(readData, typeof(T));
    } catch (InvalidCastException) {
       return default(T);
    }
}

Ответ 2

Вы пробовали Convert.ChangeType?

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

private static T ReadData<T>(XmlReader reader, string value)
{
    reader.MoveToAttribute(value);
    object readData = reader.ReadContentAsObject();
    return (T)Convert.ChangeType(readData, typeof(T));
}

Ответ 3

попробовать

if (readData is T)
    return (T)(object)readData;

Ответ 4

Вы можете потребовать, чтобы тип был ссылочным типом:

 private static T ReadData<T>(XmlReader reader, string value) where T : class
 {
     reader.MoveToAttribute(value);
     object readData = reader.ReadContentAsObject();
     return (T)readData;
 }

И затем сделайте другой, который использует типы значений и TryParse...

 private static T ReadDataV<T>(XmlReader reader, string value) where T : struct
 {
     reader.MoveToAttribute(value);
     object readData = reader.ReadContentAsObject();
     int outInt;
     if(int.TryParse(readData, out outInt))
        return outInt
     //...
 }

Ответ 5

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

Ответ 6

На самом деле проблема заключается в использовании ReadContentAsObject. К сожалению, этот метод не оправдал ожиданий; в то время как он должен обнаружить наиболее подходящий тип для значения, он фактически возвращает строку, независимо от того, что (это можно проверить с помощью Reflector).

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

Попробуйте использовать ReadContentAs, это именно то, что вам нужно.

private static T ReadData<T>(XmlReader reader, string value)
{
    reader.MoveToAttribute(value);
    object readData = reader.ReadContentAs(typeof(T), null);
    return (T)readData;
}

Ответ 7

Добавьте ограничение класса (или более подробное, например, базовый класс или интерфейс ваших объектов с расширенным T):

private static T ReadData<T>(XmlReader reader, string value) where T : class
{
    reader.MoveToAttribute(value);
    object readData = reader.ReadContentAsObject();
    return (T)readData;
}

или where T : IMyInterface или where T : new() и т.д.

Ответ 8

Собственно, ответы вызывают интересный вопрос, который вы хотите, чтобы ваша функция делала в случае ошибки.

Может быть, было бы более целесообразно построить его в виде метода TryParse, который пытается прочитать в T, но возвращает false, если это невозможно?

    private static bool ReadData<T>(XmlReader reader, string value, out T data)
    {
        bool result = false;
        try
        {
            reader.MoveToAttribute(value);
            object readData = reader.ReadContentAsObject();
            data = readData as T;
            if (data == null)
            {
                // see if we can convert to the requested type
                data = (T)Convert.ChangeType(readData, typeof(T));
            }
            result = (data != null);
        }
        catch (InvalidCastException) { }
        catch (Exception ex)
        {
            // add in any other exception handling here, invalid xml or whatnot
        }
        // make sure data is set to a default value
        data = (result) ? data : default(T);
        return result;
    }

edit: теперь, когда я думаю об этом, мне действительно нужно сделать тест convert.changetype? не как линия уже пытается это сделать? Я не уверен, что выполнение этого дополнительного вызова changetype действительно что-то делает. Фактически, это может просто увеличить накладные расходы на обработку, вызвав исключение. Если кто-то знает о различиях, которые заставляют его делать, напишите!