从String转换为<t> </t>

时间:2009-04-09 03:33:15

标签: c# xml generics

我真的应该能够得到这个,但我只是觉得它更容易提问。

在C#函数中:

public static T GetValue<T>(String value) where T:new()
{
   //Magic happens here
}

魔术的优秀实施是什么?这背后的想法是我要解析xml并且所需的值通常是基元(bool,int,string等),这是使用泛型的完美地方......但是一个简单的解决方案目前正在躲避我

顺便说一下,这是我需要解析的xml示例

<Items>
    <item>
        <ItemType>PIANO</ItemType>
        <Name>A Yamaha piano</Name>
        <properties>
            <allowUpdates>false</allowUpdates>
            <allowCopy>true</allowCopy>
        </properties>   
    </item>
    <item>
        <ItemType>PIANO_BENCH</ItemType>
        <Name>A black piano bench</Name>
        <properties>
            <allowUpdates>true</allowUpdates>
            <allowCopy>false</allowCopy>
            <url>www.yamaha.com</url>
        </properties>
    </item>
    <item>
        <ItemType>DESK_LAMP</ItemType>
        <Name>A Verilux desk lamp</Name>
        <properties>
            <allowUpdates>true</allowUpdates>
            <allowCopy>true</allowCopy>
            <quantity>2</quantity>
        </properties>
    </item>
</Items>

5 个答案:

答案 0 :(得分:149)

我建议您不要尝试自己解析XML,而是尝试创建可以从XML反序列化到类中的类。我会强烈建议遵循bendewey的回答。

但如果你不能这样做,那就有希望了。您可以使用Convert.ChangeType

public static T GetValue<T>(String value)
{
  return (T)Convert.ChangeType(value, typeof(T));
}

并使用如此

GetValue<int>("12"); // = 2
GetValue<DateTime>("12/12/98");

答案 1 :(得分:5)

你可以从大致类似的东西开始:

TypeConverter converter = TypeDescriptor.GetConverter(typeof(T));
if (converter != null)
{
   return (T)converter.ConvertFrom(value);
}

如果你必须解析特殊类型的属性,比如颜色或文化字符串或诸如此类的东西,你当然必须在上面构建特殊情况。但这将处理大多数原始类型。

答案 2 :(得分:4)

如果您决定将序列化路线转到POCO(普通旧CLR对象),那么很少有工具可以帮助您生成对象。

  • 您可以使用xsd.exe根据XML定义生成.cs文件
  • WCF REST Starter Kit Preview 2中有一项新功能,名为Paste as Html。这个功能非常酷,让你可以在剪贴板中获取一块HTML,然后当你将它粘贴到cs文件中时,它会自动将xml转换为CLR对象进行序列化。

答案 3 :(得分:0)

为了使其正常工作,您的通用方法必须将其实际工作委托给专用类。

这样的东西
private Dictionary<System.Type, IDeserializer> _Deserializers;
    public static T GetValue<T>(String value) where T:new()
    {
       return _Deserializers[typeof(T)].GetValue(value) as T;
    }

其中_Deserializers是您注册课程的某种字典。 (显然,需要进行一些检查以确保在字典中注册了反序列化器。)

(在这种情况下,T:new()的位置是无用的,因为你的方法不需要创建任何对象。

答案 4 :(得分:0)

再次警告说,这样做可能是一个坏主意:

class Item 
{
    public string ItemType { get; set; }
    public string Name { get; set; }
}

public static T GetValue<T>(string xml) where T : new()
{
    var omgwtf = Activator.CreateInstance<T>();
    var xmlElement = XElement.Parse(xml);
    foreach (var child in xmlElement.Descendants())
    {
        var property = omgwtf.GetType().GetProperty(child.Name.LocalName);
        if (property != null) 
            property.SetValue(omgwtf, child.Value, null);
    }
    return omgwtf;
}

试运行:

static void Main(string[] args)
{
    Item piano = GetValue<Item>(@"
        <Item>
            <ItemType />
            <Name>A Yamaha Piano</Name>
            <Moose>asdf</Moose>
        </Item>");
}