簡體   English   中英

從String轉換為<T>

[英]Converting from String to <T>

我真的應該能夠得到這個,但我只是覺得它更容易問。

在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>

我建議您不要嘗試自己解析XML,而是嘗試創建可以從XML反序列化到類中的類。 強烈建議遵循bendewey的回答。

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

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

並使用這樣的

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

你可以從大致這樣的東西開始:

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

如果你必須解析特殊類型的屬性,比如顏色或文化字符串或諸如此類的東西,你當然必須在上面構建特殊情況。 但這將處理大多數原始類型。

如果您決定將序列化的路徑轉到POCO(普通的舊CLR對象),那么很少有工具可以幫助您生成對象。

  • 您可以使用xsd.exe根據XML定義生成.cs文件
  • WCF REST入門套件預覽版2中有一項新功能,名為Paste as Html。 這個功能非常酷,可以讓你在剪貼板中取出一塊HTML,然后當你將它粘貼到cs文件中時,它會自動將xml轉換為CLR對象進行序列化。

為了使其正常工作,您的泛型方法將必須將其實際工作委托給專用類。

就像是

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()的位置是無用的,因為您的方法不需要創建任何對象。

再次提醒,這樣做可能是一個壞主意:

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>");
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM