web-dev-qa-db-ja.com

文字列から<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>
57
Saint Domino

自分でXMLを解析する代わりに、XMLからクラスに逆シリアル化するクラスを作成することをお勧めします。私は強くベンデウェイの答えに従うことをお勧めします。

しかし、これができない場合、希望があります。 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");
153
Samuel

おおよそ次のようなものから始めることができます:

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

色やカルチャ文字列など、特別なタイプの属性を解析する必要がある場合は、もちろん上記に特別なケースを組み込む必要があります。しかし、これはほとんどのプリミティブ型を処理します。

5
womp

POCO(Plain old CLR Object)へのシリアル化のルートを選択する場合、オブジェクトの生成に役立つツールはほとんどありません。

  • xsd.exe を使用して、XML定義に基づいて.csファイルを生成できます。
  • WCF REST Starter Kit Preview 2 には、Htmlとして貼り付けと呼ばれる新しい機能があります。この機能は本当にクールで、HTMLのブロックを取得できます。クリップボードをcsファイルに貼り付けると、シリアル化のためにxmlがCLRオブジェクトに自動的に変換されます。
4
bendewey

これが正しく機能するためには、ジェネリックメソッドが実際の作業を専用のクラスに委任する必要があります。

何かのようなもの

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()は役に立たない。

0
Denis Troller

繰り返しますが、これを行うのはおそらく悪い考えです。

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