Cast object to T

中的 XmlReader类解析 XML 文件。NET,我认为编写一个通用的解析函数来通用地读取不同的属性是明智的。我想出了以下函数:

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

正如我逐渐意识到的,这并不完全像我计划的那样工作; 它抛出了一个基本类型(如 intdouble)的错误,因为强制转换无法从 string转换为数值类型。有没有什么方法可以修改我的函数?

148428 次浏览

First check to see if it can be cast.

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

你试过 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));
}

添加一个“ class”约束(或者更详细,比如预期 T 对象的基类或接口) :

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

or where T : IMyInterface or where T : new(), etc

您大概可以将一个委托作为参数传入,该委托将从 string 转换为 T。

You could require the type to be a reference type :

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

And then do another that uses value types and 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
//...
}

try

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

实际上,这些响应提出了一个有趣的问题,即在出现错误的情况下,您希望函数执行什么操作。

也许以 TryParse 方法的形式构造它更有意义,该方法尝试读入 T,但如果不能读入 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 调用是否真的能完成任何事情。实际上,它可能只是通过生成异常来增加处理开销。如果任何人知道一个差异,使它值得做,请张贴!

实际上,这里的问题是使用 ReadContentAsObject。不幸的是,这个方法没有达到它的预期; 虽然它应该检测值的最合适的类型,但是它实际上返回了一个字符串,不管是什么(这可以通过反射器进行验证)。

但是,在您的特定情况下,您已经知道要强制转换到的类型,因此我认为您使用了错误的方法。

Try using ReadContentAs instead, it's exactly what you need.

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