我正在使用.NET中的XmlReader
类解析XML文件,我认为编写通用解析函数来一般性地读取不同的属性会很聪明。我提出了以下功能:
private static T ReadData<T>(XmlReader reader, string value)
{
reader.MoveToAttribute(value);
object readData = reader.ReadContentAsObject();
return (T)readData;
}
当我意识到,这并不像我原先计划的那样完全有效;它会导致int
或double
等基本类型出错,因为强制转换无法从string
转换为数字类型。有没有办法让我的功能以修改后的形式占上风?
答案 0 :(得分:178)
首先检查是否可以施放。
if (readData is T) {
return (T)readData;
}
try {
return (T)Convert.ChangeType(readData, typeof(T));
}
catch (InvalidCastException) {
return default(T);
}
答案 1 :(得分:15)
您是否尝试过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));
}
答案 2 :(得分:7)
试
if (readData is T)
return (T)(object)readData;
答案 3 :(得分:3)
您可以要求类型为引用类型:
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
//...
}
答案 4 :(得分:3)
实际上,这里的问题是使用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;
}
答案 5 :(得分:2)
您可以将参数作为参数传入一个将从字符串转换为T的委托。
答案 6 :(得分:1)
添加一个'class'约束(或更详细的约束,比如你预期的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()
等
答案 7 :(得分:1)
实际上,这些回复会提出一个有趣的问题,这就是你希望你的函数在出错的情况下做的事情。
以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;
}
编辑:现在我考虑一下,我真的需要做convert.changetype测试吗? as line是不是已经尝试过这样做了?我不确定做那个额外的changetype调用实际上完成了什么。实际上,它可能只是通过生成异常来增加处理开销。如果有人知道值得做的差异,请发帖!