Я разбираю 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
в числовой тип. Есть ли способ, чтобы моя функция преобладала в измененной форме?
Ответ 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 действительно что-то делает. Фактически, это может просто увеличить накладные расходы на обработку, вызвав исключение. Если кто-то знает о различиях, которые заставляют его делать, напишите!