web-dev-qa-db-fra.com

Conversion de chaîne en <T>

Je devrais vraiment pouvoir l'obtenir, mais je suis juste au point où je pense que ce serait plus facile à demander.

Dans la fonction C #:

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

Qu'est-ce qu'une bonne implémentation pour la magie? L'idée derrière cela est que j'ai du xml à analyser et que les valeurs souhaitées sont souvent primitives (bool, int, string, etc.) et c'est l'endroit idéal pour utiliser des génériques ... mais une solution simple m'échappe pour le moment .

btw, voici un échantillon du xml que j'aurais besoin d'analyser

<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

Je suggérerais au lieu d'essayer d'analyser XML vous-même, vous essayez de créer des classes qui désérialiseraient du XML dans les classes. Je recommande fortement de suivre la réponse de Bendewey.

Mais si vous ne pouvez pas faire cela, il y a de l'espoir. Vous pouvez utiliser Convert.ChangeType .

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

Et utiliser comme ça

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

Vous pouvez commencer avec quelque chose comme ceci:

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

Si vous devez analyser des attributs qui sont des types spéciaux, comme des chaînes de couleurs ou de culture ou autres, vous devrez bien sûr créer des cas spéciaux dans ce qui précède. Mais cela gérera la plupart de vos types primitifs.

5
womp

Si vous décidez de suivre la voie de la sérialisation vers POCO (Plain old CLR Object), il existe peu d'outils qui peuvent vous aider à générer vos objets.

  • Vous pouvez utiliser xsd.exe pour générer un fichier .cs basé sur votre définition XML
  • Il y a une nouvelle fonctionnalité dans le WCF REST Starter Kit Preview 2 , appelée Coller en Html. Cette fonctionnalité est vraiment cool et vous permet de prendre un bloc de code HTML dans votre presse-papiers, puis lorsque vous le collez dans un fichier cs, il convertit automatiquement le xml en objet CLR pour la sérialisation.
4
bendewey

Pour que cela fonctionne correctement, votre méthode générique devra déléguer son travail réel à une classe dédiée.

Quelque chose comme

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

où _Deserializers est une sorte de dictionnaire où vous enregistrez vos classes. (évidemment, une vérification serait nécessaire pour s'assurer qu'un désérialiseur a été enregistré dans le dictionnaire).

(Dans ce cas, où T: new () est inutile car votre méthode n'a besoin de créer aucun objet.

0
Denis Troller

encore une fois avec la mise en garde que faire cela est probablement une mauvaise idée:

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

essai:

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