2009-04-09 10 views
43

私は本当にこれを得ることができるはずですが、私はそれが求めやすいと思うところです。 C#関数で文字列から<T>への変換

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> 
+0

はあなたが解析しようとしているあなたのXMLのサンプルを提供することができます – bendewey

+0

あなたは何を期待しているのかのサンプルを提供したいですか?この文脈でTは多くのことができます。文字列をそれらに変換する能力は、許可されているものをどれだけうまく定義できるかによって異なります。 – Shog9

答えて

116

を解析する必要があると思い、XMLのサンプルです、あなたはクラスにXMLからデシリアライズしまうクラスを作成しよう。私は強くがベンドウイの答えに従うことをお勧めします。

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

POCOへのXMLシリアライズ+1 – bendewey

+0

あなたの+1を見てもう一度+1します。私はそのエレガンスによって混乱していますが、これはジェネリック薬のためにジェネリック薬を使用するようなにおいがします。 – jfar

+0

GetValueの美学について論じることができます()vs(int)GetValue():P – Jimmy

5

あなたは大体このような何かを始めることができるように使用:あなたは色や文化の文字列のような特殊な種類の属性を、解析する必要がある場合

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

もちろん、特別なケースを上記に組み込む必要があります。しかし、これはあなたの原始的な型のほとんどを処理します。

+0

GetConverter(typeof(T))を使用する場合は、変数tまたはnew()は不要です。 –

+0

ええ、私は本当に素早くそれを荒らしました。たぶん、私はそれに編集をお願いします - ありがとう。 – womp

0

これが正しく動作するためには、一般的な方法では実際の作業を専用クラスに委任する必要があります。 _Deserializersはあなたのクラスを登録辞書のいくつかの種類である

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

よう

何か。 (明らかに、デシリアライザが辞書に登録されていることを確認するためには何らかのチェックが必要です)。

(その場合には、T:あなたの方法は、任意のオブジェクトを作成する必要はありませんので、新しい()は無意味です

+0

whereクラスの制約がないジェネリック型でas演算子を使用することはできません。 – Samuel

+0

woops、それを知らなかった。あなたはまだ普通のキャスト私は推測することができますか? –

4

あなたはPOCO(昔ながらのCLRオブジェクト)へのシリアライズのルートを行くことにした場合、その後、あなたのオブジェクトを生成することができますいくつかのツールがあります。

  • あなたのXML定義に基づいた.csファイルを生成するためにxsd.exeを使用することができます
  • HTMLとして貼り付け]と呼ばれる WCF REST Starter Kit Preview 2の新機能があり、
  • この機能は本当にクールで、HTMLのブロックを取ることができますcsファイルに貼り付けると、自動的にXMLをCLRオブジェクトに変換してシリアル化します。これを行うことはおそらく悪い考えであることを警告して再び
+0

シリアライゼーションは、この関数の意図された使用については問題になりません。我々はXml <-> pocoを最初に考えましたが、xmlが> 1Mbの範囲に達すると、アプリがダウンすることがありました。上司はxpathが行く方法だと言っている –

+0

LINQ to XMLはxpathより高速です。 – bendewey

+0

http://en.wikipedia.org/wiki/XML#Processing_filesを参照してください、XPathはDOMを使用し、LinqはXMLに「プルパース」を使用します – bendewey

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>"); 
} 
関連する問題