IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++/CLI Discussion :

Externaliser les données d'un Dictionary


Sujet :

C++/CLI

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    254
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2007
    Messages : 254
    Points : 55
    Points
    55
    Par défaut Externaliser les données d'un Dictionary
    Bonjour,
    a fin d'éviter que le dictionnaire ne se charge au démarrage je souhaite le créer dans un data.h ou un fichier externe a l'application ex data.** ce qui faciliterai les ajout futur mais je n'y arrive pas.
    Actuellement mon dictionnaire est intégré à l'appli comme si dessous.
    Merci d'avance pour votre aide.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
     
    	public ref class Form1 : public System::Windows::Forms::Form
    	{
    	public:
    		Form1(void)
    		{
    			InitializeComponent();
     
    			dict = gcnew Dictionary< String^, TwoStrings^ >;
    			TwoStrings ^TwoStrs = gcnew TwoStrings;
    			TwoStrs = gcnew TwoStrings;
    			TwoStrs->first = L"arbre";
    			TwoStrs->second = L"ete";
    			dict->Add(L"3452", TwoStrs);TwoStrs = gcnew TwoStrings;
     
            }
            private 
     
    		Dictionary<String, FourStrings> dict;
    Et dans un autre fichier d'en-tête.h la classe FourStrings
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    namespace dico {
    	using namespace System;
     
    	public ref class FourStrings {
    	public:
    		String^ first;
    		String^ second;
    		String^ three;
     	        String^ four;
    	};
    }

  2. #2
    Membre du Club
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    254
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2007
    Messages : 254
    Points : 55
    Points
    55
    Par défaut
    Es ce possible de mettre mon dico dans un dataTable? ou autre base?
    Un exemple serait le bien venu,merci.

  3. #3
    Expert éminent sénior
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 078
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 078
    Points : 12 131
    Points
    12 131
    Par défaut
    La méthode de feignant : Google :

    http://weblogs.asp.net/pwelter34/arc...03/444961.aspx

    Il y a peut-être plus élégant en .NET4.

    Avec ce dictionnaire serialisable, vous mettez vos données dans le fichier de configuration au format attendu par cette classe et vous chargez ce dictionnaire comme une ressource standard.
    What else.

  4. #4
    Membre du Club
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    254
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2007
    Messages : 254
    Points : 55
    Points
    55
    Par défaut

    Bonsoir,

    Je cherche depuis un bon moment sur Google mais le xml j'ai préféré laisser e coté car je n'y connais rien.

    Dans la classe si j'ai bien compris il me faut dans :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    public System.Xml.Schema.XmlSchema GetSchema() 
    //créer un schéma pour la Tkey et la Tvalue 
    //Dans un fichier xml écrire mes  TKey,TValue. 
    while (reader.NodeType != System.Xml.XmlNodeType.EndElement){...}
    //Je comprend pas la démarche pour lire, chercher et afficher.
    Le fichier XML peut il être externe à l'application ou forcément inclus?
    Désolé si mes questions peuvent paraître stupides mais sans réponses il m'est difficile d'avancer.

  5. #5
    Expert éminent sénior
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 078
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 078
    Points : 12 131
    Points
    12 131
    Par défaut
    mais le xml j'ai préféré laisser e coté car je n'y connais rien.
    Vous allez voir, ce n’est pas trop compliqué et c'est super pratique.

    Le principe de la solution que je vous montre est simple.
    On utilise le principe de la sérialisation et désérialisation.
    La sérialisation, c'est transformer un objet en chaine de caractère.
    Et la désérialisation, c'est transformer une chaîne de caractère en objet.

    On va donc prendre le contenu d'un fichier comme chaine en entré du mécanisme de désérialisation et obtenir votre cher dictionnaire.

    Une méthode de sérialisation/désérialisation est d'utiliser le XML comme format de chaine de caractère.

    Le seul truc un peu compliqué, c'est que .NET (même la version 4, après un petit teste) interdit la sérialisation des IDictionary donc des objets de la classe Dictionary<T,U>.

    On va donc créer une classe dérivant de Dictionary<T,U> et qui sera sérialisable.

    En convertissant, à l'arrache, le code C# trouvé à cette URL :
    http://www.dacris.com/blog/2010/07/3...ngExample.aspx
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    using namespace System;
    using namespace System::Collections::Generic;
    using namespace System::IO;
    using namespace System::Runtime::Serialization;
    using namespace System::Xml;
    using namespace System::Xml::Serialization;
    using namespace System::Xml::Schema;
     
    generic <typename TKey, typename TVal>
    [Serializable()]
    public ref class SerializableDictionary : Dictionary<TKey,TVal>, IXmlSerializable, ISerializable
    {
    private :
    	static String^ DictionaryNodeName = "Dictionary";
    	static String^ ItemNodeName = "Item";
    	static String^ KeyNodeName = "Key";
    	static String^ ValueNodeName = "Value";
     
    public:
    	SerializableDictionary(){}
     
    	SerializableDictionary(IDictionary<TKey, TVal>^ dictionary)
    		: Dictionary<TKey,TVal>(dictionary)
    	{}
     
    	SerializableDictionary(IEqualityComparer<TKey>^ comparer)
    		: Dictionary<TKey,TVal>(comparer)
    	{}
     
    	SerializableDictionary(int capacity)
    		: Dictionary<TKey,TVal>(capacity)
    	{}
     
    	SerializableDictionary(IDictionary<TKey, TVal>^ dictionary, IEqualityComparer<TKey>^ comparer)
    		: Dictionary<TKey,TVal>(dictionary, comparer)
    	{}
     
    	SerializableDictionary(int capacity, IEqualityComparer<TKey>^ comparer)
    		: Dictionary<TKey,TVal>(capacity, comparer)
    	{}
     
    protected :
     
    	SerializableDictionary(SerializationInfo^ info, StreamingContext* context)
    	{
    		int itemCount = info->GetInt32("ItemCount");
     
    		for (int i = 0; i < itemCount; i++)
    		{
    			KeyValuePair<TKey, TVal>^ kvp = (KeyValuePair<TKey, TVal>^)info->GetValue(String::Format("Item{0}", i), KeyValuePair<TKey, TVal>::typeid );
    			this->Add(kvp->Key, kvp->Value);
    		}
    	}
     
    public :
     
    	virtual void GetObjectData(SerializationInfo^ info, StreamingContext context) override = ISerializable::GetObjectData
    	{
    		info->AddValue("ItemCount", this->Count);
     
    		int itemIdx = 0;
    		for each (KeyValuePair<TKey, TVal>^ kvp in this)
    		{
    			info->AddValue(String::Format("Item{0}", itemIdx), kvp, KeyValuePair<TKey, TVal>::typeid);
    			itemIdx++;
    		}
     
    	}
     
    	virtual void WriteXml(XmlWriter^ writer) = IXmlSerializable::WriteXml
    	{
    		//writer.WriteStartElement(DictionaryNodeName);
     
    		for each (KeyValuePair<TKey, TVal>^ kvp in this)
    		{
    			writer->WriteStartElement(ItemNodeName);
    			writer->WriteStartElement(KeyNodeName);
    			KeySerializer->Serialize(writer, kvp->Key);
    			writer->WriteEndElement();
    			writer->WriteStartElement(ValueNodeName);
    			ValueSerializer->Serialize(writer, kvp->Value);
    			writer->WriteEndElement();
    			writer->WriteEndElement();
    		}
     
    		//writer.WriteEndElement();
    	}
     
    	virtual void ReadXml(XmlReader^ reader) = IXmlSerializable::ReadXml
    	{
    		if (reader->IsEmptyElement)
    		{
    			return;
    		}
     
    		// Move past container
     
    		if (!reader->Read())
    		{
    			throw gcnew XmlException("Error in Deserialization of Dictionary");
    		}
     
    		//reader.ReadStartElement(DictionaryNodeName);
     
    		while (reader->NodeType != XmlNodeType::EndElement)
    		{
    			reader->ReadStartElement(ItemNodeName);
    			reader->ReadStartElement(KeyNodeName);
    			TKey key = (TKey)KeySerializer->Deserialize(reader);
    			reader->ReadEndElement();
    			reader->ReadStartElement(ValueNodeName);
    			TVal value = (TVal)ValueSerializer->Deserialize(reader);
    			reader->ReadEndElement();
    			reader->ReadEndElement();
    			this->Add(key, value);
    			reader->MoveToContent();
    		}
     
    		//reader.ReadEndElement();
     
    		reader->ReadEndElement(); // Read End Element to close Read of containing node
    	}
     
    	virtual XmlSchema^ GetSchema() = IXmlSerializable::GetSchema
    	{
    		return nullptr;
    	}
     
    protected :
    	property XmlSerializer^ ValueSerializer
    	{
    		XmlSerializer^ get()
    		{
    			if (valueSerializer == nullptr)
    			{
    				valueSerializer = gcnew XmlSerializer(TVal::typeid);
    			}
    			return valueSerializer;
    		}
    	}
     
    private :
    	property XmlSerializer^ KeySerializer
    	{
    		XmlSerializer^ get()
    		{
    			if (keySerializer == nullptr)
    			{
    				keySerializer = gcnew XmlSerializer(TKey::typeid);
    			}
    			return keySerializer;
    		}
    	}
     
    	XmlSerializer^ keySerializer;
    	XmlSerializer^ valueSerializer;
    };
    En utilisant un SerializableDictionary en lieu et place d'un Dictionary, vous pourrez le sérialiser et le désérialiser.

    Pour que la classe issue de l'expansion de la classe générique SerializableDictionary reste sérialisable et désérialisable, il faut que le type du paramètre générique soit aussi un type sérialisable.

    Voici en exemple de classe sérialisable.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    [Serializable()]
    public ref class Values
    {
    public :
    	Values(){};
    	Values(String ^ s1, String ^ s2){Value1 = s1; Value2 = s2;};
     
    	String^ Value1;
    	String^ Value2;
    };
    Remarquez l'attribut [Serializable()], le constructeur public sans paramètre et les champs avec une visibilité "public". C'est un moyen simple de rendre la classe sérialisable et désérialisable.

    Il ne reste plus qu'à avoir un simple fichier texte correctement formaté, comme celui-ci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    <?xml version="1.0" encoding="utf-8"?>
    <SerializableDictionaryOfStringValues>
      <Item>
        <Key>
          <string>cle1</string>
        </Key>
        <Value>
          <Values>
            <Value1>text1</Value1>
            <Value2>text2</Value2>
          </Values>
        </Value>
      </Item>
    </SerializableDictionaryOfStringValues>
    Le format du fichier est fonction de la classe de la clé et de la classe des entrées dans le dictionnaire. Dans notre exemple c'est "String ^" et "Values ^".
    Si vous utilisez d’autres types comme paramètres générique, il faudra modifier le format du fichier. Dans le code ci-après, la méthode "create", mise en commentaire, permettra de générer un fichier contenant un objet sérialisé correctement formaté qui vous servira d'exemple en cas de besoin. Cette méthode utilise la sérialisation d'un objet SerializableDictionary<T,U>.

    Pour pouvoir créer le dictionnaire, rien de plus simple, il suffit d'utiliser la classe XmlSerializer^ pour le récupérer depuis le contenu du fichier, comme le montre le code la méthode "read" ci-après.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    void create(XmlSerializer^ serializer)
    {
    	SerializableDictionary<String ^, Values ^>^ dico = gcnew SerializableDictionary<String ^, Values ^>;
    	Values ^ element = gcnew Values("text1","text2");
    	dico->Add("cle1", element);
     
    	TextWriter^ writer = gcnew StreamWriter( "test.xml" );
    	serializer->Serialize( writer, dico );
    	writer->Close();
    }
     
    SerializableDictionary<String ^, Values ^>^ read(XmlSerializer^ serializer)
    {
    	TextReader^ reader = gcnew StreamReader( "test.xml" );
    	SerializableDictionary<String ^, Values ^>^ ret = (SerializableDictionary<String ^, Values ^>^) serializer->Deserialize( reader);
    	reader->Close();
    	return ret;
    }
     
    int main(array<System::String ^> ^args)
    {
    	XmlSerializer^ serializer = gcnew XmlSerializer( SerializableDictionary<String ^, Values ^>::typeid );
    	//create(serializer);
     
    	SerializableDictionary<String ^, Values ^>^ dico = read(serializer);
     
    	Values^ Values = dico["cle1"];
    	return 0;
    }
    L'utilisation du XML permet d'avoir un fichier texte extrêmement facile à modifier et simple avec un minimum de connaissance en XML.

  6. #6
    Membre du Club
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    254
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2007
    Messages : 254
    Points : 55
    Points
    55
    Par défaut

    Ok j'ai compris dans les grandes lignes, mais ça commence mal, je n'arrive pas a declarer la classe XmlSerializer^ ,j'ai juste fait un copier coller du code de la classe dans un projet vide et ça refuse de compiler avec l'erreur:
    error C2065: 'SerializableDictionary'*: identificateur non déclaré

    J'ai bien entendu mis les namespaces comme vous les avez décrit.
    Dois-je déclarer cette classe dans un autre fichier .h ?

  7. #7
    Expert éminent sénior
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 078
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 078
    Points : 12 131
    Points
    12 131
    Par défaut
    Désolé pour le retard.

    'SerializableDictionary' est une classe définie dans le premier bloc "Code" de mon dernier post.

    Normalement, en mettant le premier bloc "Code", le premier bloc "Quote" (une erreur, vue que c'est du code) et le deuxième et dernier bloc "Code" dans un seul fichier cpp, cela compilera.

    A vous d'organiser votre code en fichier selon vos habitudes.

Discussions similaires

  1. Réponses: 3
    Dernier message: 20/01/2011, 02h00
  2. Réponses: 4
    Dernier message: 04/12/2003, 08h12
  3. Réponses: 13
    Dernier message: 14/10/2003, 14h31
  4. Réponses: 4
    Dernier message: 18/08/2003, 09h53
  5. trier les données dans le cache ??
    Par psyco2604 dans le forum XSL/XSLT/XPATH
    Réponses: 31
    Dernier message: 10/06/2003, 10h03

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo