如何使用XmlConvert将作为对象强制转换的值类型转换为字符串?

6
我正在寻找与以下代码等效的内容,但对于任何值类型都不需要编写一个switch语句来完成。 由于XmlConvert.ToString()没有接受对象的重载,因此下面的代码无法编译。
        int intValue = 10;
        object boxedValue = (object)intValue;
        string xmlValue = XmlConvert.ToString(boxedValue);

换句话说,除了这种方法,还有更好的方法吗?
public static string ToXmlString(Type type, object value) {

        switch(Type.GetTypeCode(type)) {
            case TypeCode.Int32:
                return XmlConvert.ToString((int) value);
            case TypeCode.DateTime:
                return XmlConvert.ToString((DateTime) value, XmlDateTimeSerializationMode.Unspecified);
            case TypeCode.Boolean:
                return XmlConvert.ToString((bool) value);

            // TODO:  Add case for all other value types!

            default:
                return value.ToString();
        }
    }
4个回答

1
我需要进行相反的转换(从字符串到类型),作为我想要编写的序列化器的一部分(出于某些原因,避免使用内置的序列化器)。我正在进行反序列化,这是唯一一篇讨论此问题的帖子,因此在仍然记忆犹新时,我将更新我的答案。
我使用的方法是使用反射来基本上确定我需要做什么。以下示例中的变量类型是我要转换的类型的Type对象,E是我将要转换的XmlNode的内容,newVar是我将返回的模板类型T的实例。此片段不假设任何对T的约束(这就是为什么没有直接的字符串分配/转换),并且假设对象/枚举被处理得不同(对象和枚举会破坏这一点):
MethodInfo convertMethod;

if( Type.GetTypeCode(type) != TypeCode.String )
    convertMethod = typeof(XmlConvert).GetMethod ( "To" + type.Name );
else
    convertMethod = E.InnerText.GetType().GetMethod("Clone");

if( convertMethod == null )
{
    //Error
}
else
{
    if( Type.GetTypeCode (type)!= TypeCode.String )
        newVar = (T)convertMethod.Invoke( null, new object[] { E.InnerText } );
    else
        newVar = (T)convertMethod.Invoke ( E.InnerText, new object[]{} );
}

字符串需要作为特殊情况处理,因为ToString()做的是完全不同的事情,会破坏一切。

另一种方法(根据原始帖子)可能是这样的(未经测试,如果编写序列化函数将进行更新):

MethodInfo convertMethod;

if( Type.GetTypeCode(type) != TypeCode.String )
    convertMethod = typeof(XmlConvert).GetMethod ( "ToString", new Type[] {typeof(T)} );
else
    convertMethod = typeof(string).GetMethod("Clone");

if( convertMethod == null )
{
    //Error
}
else
{
    string str;
    if( Type.GetTypeCode (type)!= TypeCode.String )
        str = (string)convertMethod.Invoke( null, new object[] { Value } );
    else
        str = (string)convertMethod.Invoke ( Value, new object[]{} );
}

在这种情况下,转换是从T到字符串,Value包含我们要转换的类型T。区别在于我们要求ToString,但指定了一个参数为T类型的函数。这应该足够独特了。

1

另一个选择是使用Reflector查看并复制System.Xml.Linq.XContainer.GetStringValue(不幸的是它是内部的)


1

所有值类型都具有固有的可序列化性。因此,您只需要使用XMLSerializer即可。 类似这样的代码就可以实现(基于您的方法):

public static string ToXmlString(Type type, object value)
{
    StringBuilder sb = new StringBuilder();
    System.Xml.XmlWriter writer = System.Xml.XmlWriter.Create(sb);
    System.Xml.Serialization.XmlSerializer serial = 
        new System.Xml.Serialization.XmlSerializer(type);
    serial.Serialize(writer, value);
}

有趣的是,如果你使用Reflector跟踪XmlSerializer.Serialize,最终会遇到一个叫做SerializePrimitive的方法,它有一个大的switch语句,分派给最终调用XmlConvert.ToString的方法,其中将对象强制转换为本机类型。 - Darrel Miller
但这是一件坏事吗?发生的一切只是将开关从您的代码移动到框架代码中。 - DarkwingDuck
1
ToXmlString(typeof(boolean), true) 的结果是 <?xml version="1.0" encoding="utf-16"?><boolean>true</boolean>,这不是预期的 "true"。必须重新映射结果才能使其正常工作。我更喜欢 Darrel 提出的“硬”方法。 - Lakedaimon
抱歉,这个怎么投票?它不像其他评论一样工作,它返回的是XML而不是预期的XML值。 - Poul K. Sørensen

0

仅供参考,您是否试图将业务对象转换为XML?

也许您想看看XmlSerialization。如果在业务对象上标记了一些属性,.Net会为您完成所有炫酷的XML操作 :)

此外,您为什么要装箱您的值?XmlConvert.ToString()有19种重载,其中许多采用原语。


我感谢你提供的信息,但我已经历了XmlSerializer、DataContractSerializer的煎熬。我甚至尝试过XamlWriter。我的值被装箱,因为我通过一个处理多种数据类型的接口来访问它们。 - Darrel Miller

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接