none
Fichiers de ressource Resx sur un site web RRS feed

  • Question

  • Bonjour tout le monde,

    J'ai testé ce matin l'interface de saisie multilingue que j'ai écrite en .Net 2, basée sur des fichiers .Resx, et ça marchait très bien.

    Elle utilise ResxResourceWriter pour écrire dans le fichier d'extension Resx. ResxResourceWriter fait partie de l'espace de noms System.Resources, dans l'assembly System.Windows.Forms.

    Souci en arrivant sur la plateforme .Net 4 : il existe un espace de noms System.Resources dans mscorlib, donc même si j'importe la référence System.Windows.Forms, le système ne voit pas System.Resources qu'il y a dedans car à la place il voit le System.Resources qu'il y a dans mscorlib, qui, comme je le vois dans l'explorateur d'objets, contient IResourceReader, IResourceWriter, MissingManifestResourceException, ResourceReader, ResourceWriter, et encore du monde, mais pas ResXResourceReader ni ResXResourceWriter, qui sont dans l'autre System.Resources, celui de System.Windows.Forms.

    Est-ce que je ne pourrais pas préfixer un des deux pour éviter la confusion ?

    Ou sinon ça veut dire qu'on ne peut pas utiliser les fichiers ResX sur un site web en .Net 4 ?

    Sur quelques sites j'ai vu un code source de l'objet ResXResourceWriter. Est-ce une invitation à l'implémenter soi-même ? Je dis ça un peu comme une boutade, tellement c'est contraire à la tendance générale d'avoir des objets incluant de plus en plus de code déjà tout prêt, et nécessitant moins de développement dans l'application finale.

    Donc en définitive, que fais-je ? En plus le client a une préférence pour le format xml, donc Resx c'est pas mal ...


    • Modifié Gloops mercredi 12 avril 2017 12:00
    lundi 3 avril 2017 14:14

Réponses

  • La réflexion m'a donné plus de fil à retordre que prévu.

    Finalement, j'en ai eu pour moins de deux heures à implémenter moi-même un ResXResourceWriter pour le web, après avoir effectué la lecture dans le code de la DataGrid, mais le ResXResourceReader pourrait être implémenté sur le même principe.

    Je n'ai mis là-dedans que ce que j'utilise, il n'y a donc pas tous les membres du ResXResourceWriter traditionnel de System.Windows.Forms, mais il y a moyen de créer des ressources texte dans un fichier de ressource au chemin donné en argument. Si le fichier existe déjà, une exception est levée au moment de l'enregistrement, et les ressources sauvegardées dans un fichier temporaire dont le nom a été noté lors de l'ouverture. Attention je me base sur un fichier de ressource vide, SourceRessource.xml, qui se trouve dans le répertoire App_Data, comme il est facile à obtenir (en l'ouvrant en mode texte) je ne le reproduis pas ici.

    Le message d'erreur apparaît en Français, c'est un point qu'on peut améliorer.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Xml;
    using System.Xml.Linq;
    using System.IO;
    
    namespace GestionRessources
    {
        public class ResXResourceWriter
        {
            
            private XmlDocument _xDoc = null;
            private XmlNode _root = null;
            private string _strPath = null;
            private string _strPathErr = null;
    
            public XmlDocument XDoc
            {
                get
                {
                    return _xDoc;
                }
            }
    
            public XmlNode Root
            {
                get
                {
                    return _root;
                }
    
            }
            
            public string PathOfFile
            {
                get
                {
                    return _strPath;
                }
            }
    
            public ResXResourceWriter(string strFilePath)
            {
                _strPath = strFilePath;
                string strPathSourceXml = HttpContext.Current.Server.MapPath(@"~\App_Data\SourceRessource.xml");
                _xDoc = new XmlDocument();
                if(File.Exists(_strPath))
                {
                    _strPathErr = Path.Combine(Path.GetDirectoryName(strFilePath), (Path.GetRandomFileName() + ".resx"));
                    strFilePath = _strPathErr;
                }
                File.Copy(strPathSourceXml, strFilePath);
                XDoc.Load(strFilePath);
                _root = XDoc.DocumentElement ;
    
            }
    
            public bool AddResource(string NomRessource, string Contenu)
            {
                AddResource(NomRessource, Contenu, "");
                return true;
            }
    
            public bool AddResource(string NomRessource, string Contenu, string Commentaire)
            {
                XmlElement nod = XDoc.CreateElement(string.Empty, "data", string.Empty);
                XmlAttribute att = XDoc.CreateAttribute("name");
                att.Value = NomRessource;
                nod.Attributes.Append(att);
                att = XDoc.CreateAttribute("xml:space");
                att.Value = "preserve";
                nod.Attributes.Append(att);
    
                XmlElement el = XDoc.CreateElement(string.Empty, "value", string.Empty);
                el.InnerText = Contenu;
    
                nod.AppendChild(el);
    
                if(!String.IsNullOrEmpty(Commentaire))
                {
                    XmlElement elC = XDoc.CreateElement(string.Empty, "comment", string.Empty);
                    elC.InnerText = Commentaire;
                    nod.AppendChild(elC);
                }
    
                Root.AppendChild(nod);
    
                return true;
            }
    
            public void Close()
            {
    
                try
                {
                    if (String.IsNullOrEmpty(_strPathErr))
                    {
                        XDoc.Save(_strPath);
                    }
                    else
                    {
                        XDoc.Save(_strPathErr);
                    }
                }
                catch(Exception ex)
                {
                    throw ex;
                }
                if (!String.IsNullOrEmpty(_strPathErr))
                {
                    throw new Exception(String.Format("Fichier <br /><i>{0}</i> <br /><br />déjà existant, sauvegarde effectuée sous <br /><br /><i>{1}</i>", _strPath, _strPathErr));
                }
            }
    
    
        }
    }


    Exemple de procédure appelante :

            protected void Button1_Click(object sender, EventArgs e)
            {
    
                try
                {
                    ResXResourceWriter ResX = new ResXResourceWriter(@"C:\Users\bibi\documents\visual studio 2013\Projects\GestionRessources\GestionRessources\App_GlobalResources\Resource2.resx");
                    foreach (EltRessource elt in GestionRessources.App_Code.Param.LstEntree)
                    {
                        ResX.AddResource(elt.NomRessource, elt.Traduction, elt.CommentaireTraduction);
                    }
                    lblReponse.Text = "Sauvegarde effectuée sous " + ResX.PathOfFile;
                    ResX.Close();
                }
                catch(Exception ex)
                {
                    lblReponse.Text = ex.Message;
                    lblReponse.ForeColor = System.Drawing.Color.Red;
                }
                Button1.Visible = false;
            }
        }

    Ah, oui, vous avez vu que je me suis basé sur une classe décrivant une ressource, qui s'appelle EltRessource ; j'ai aussi créé une classe statique Param où je stocke une copie de la liste de ressources.

    Voici EltRessource :

    using System;
    using System.Data;
    using System.Configuration;
    using System.Web;
    using System.Web.Security;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Web.UI.WebControls.WebParts;
    using System.Web.UI.HtmlControls;
    using System.Collections.Generic;
    using System.Xml.Linq;
    using System.Diagnostics;
    using System.Xml;
    using System.Data;
    
    
    namespace GestionRessources
    {
    
        /// <summary>
        /// Description résumée de EltRessource
        /// </summary>
        /// <exclude/>
        public class EltRessource
        {
            /// <summary>
            ///
            /// </summary>
            /// <param name="Nom"></param>
            /// <param name="ValeurInitiale"></param>
            /// <param name="Commentaire"></param>
            public EltRessource(string Nom, string ValeurInitiale, string Commentaire)
            {
                _NomRessource = Nom;
                _Valeur = ValeurInitiale;
                _Comment = Commentaire;
            }
    
            public EltRessource()
            {
    
            }
    
            private string _NomRessource;
    
            private string _Valeur;
    
            private string _Comment;
    
            private string _Traduction;
    
            private string _CommentaireTraduction;
    
    
            /// <summary>
            ///
            /// </summary>
            /// <exclude />
            public string Comment
            {
                get { return _Comment; }
                set { _Comment = value; }
            }
    
            /// <summary>
            ///
            /// </summary>
            /// <exclude />
            public string Valeur
            {
                get { return _Valeur; }
                set { _Valeur = value; }
            }
    
            /// <summary>
            ///
            /// </summary>
            /// <exclude />
            public string NomRessource
            {
                get { return _NomRessource; }
                set { _NomRessource = value; }
            }
    
            public string Traduction
            {
    
                get { return _Traduction; }
    
                set { _Traduction = value; }
            }
    
            public string CommentaireTraduction
            {
                get { return _CommentaireTraduction; }
                set { _CommentaireTraduction = value; }
            }
    
            public Object GetContent()
            {
                if (GestionRessources.App_Code.Param.LstEntree == null)
                {
                    List<EltRessource> LstEntree = new List<EltRessource>();
                    XmlDocument X = new XmlDocument();
                    string strPath = @"C:\Users\bibi\Documents\visual studio 2013\Projects\GestionRessources\GestionRessources\App_GlobalResources\Resource1.resx";
                    X.Load(strPath);
                    XmlNodeList Contenu = X.SelectNodes("root/data");
                    foreach (XmlNode nod in Contenu)
                    {
                        string Nom = null;
                        string ValeurInitiale = null;
                        string Commentaire = null;
                        Debug.Print("{0} : {1}", nod.Attributes["name"].Value, nod.SelectSingleNode("value").InnerText);
                        Nom = nod.Attributes["name"].Value;
                        ValeurInitiale = nod.SelectSingleNode("value").InnerText;
                        if (nod.SelectNodes("comment").Count > 0)
                        {
                            Debug.Print(nod.SelectSingleNode("comment").InnerText);
                            Commentaire = nod.SelectSingleNode("comment").InnerText;
                        }
                        EltRessource Elt = new EltRessource(Nom, ValeurInitiale, Commentaire);
                        LstEntree.Add(Elt);
                    }
    
                    GestionRessources.App_Code.Param.LstEntree = LstEntree;
    
                    return LstEntree;
                }
                else
                {
                    return GestionRessources.App_Code.Param.LstEntree;
                }
            }
    
            public Object Edit(string inNomRessource, string inTraduction)
            {
                List<GestionRessources.EltRessource> LstEntree = GestionRessources.App_Code.Param.LstEntree;
                EltRessource Sel = null;
                foreach(EltRessource Elt in LstEntree)
                {
                    if(Elt.NomRessource.Equals(inNomRessource))
                    {
                        Sel = Elt;
                    }
                }
                Sel.Traduction = inTraduction;
                return true;
            }
    
            private static bool Trouve(EltRessource o, string inNomRessource)
            {
                return o.NomRessource.Equals(inNomRessource);
            }
    
        }
    }

    Et, en sortant un peu du sujet, j'ai noté que sous Visual Studio 2013 (c'est valable à partir du 2012), après avoir créé une classe dans App_Code, il faut, dans ses propriétés, modifier l'attribut "Action de génération" en "Compiler" plutôt que "Contenu", sinon la classe n'est pas reconnue dans le code.





    • Marqué comme réponse Gloops jeudi 6 avril 2017 12:25
    • Modifié Gloops jeudi 6 avril 2017 12:43
    jeudi 6 avril 2017 12:24

Toutes les réponses

  • Ah, j'ai peut-être une piste ...

    Si j'exécute ça :

                Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
                Object rr = null;
                Object rw = null;
                int inbAss = assemblies.Count();
                Assembly ass = null;
                var ena = assemblies.GetEnumerator();
                System.Diagnostics.Debug.Write(ena.GetType().ToString());
                foreach(Assembly a in assemblies)
                {
                    string str = a.GetName().ToString();
                    System.Diagnostics.Debug.WriteLine(str);
                    char[] sep = {','};
                    if(str.Split(sep)[0].Equals("System.Windows.Forms"))
                    {
                        foreach(Type T in a.GetTypes())
                        {
                            System.Diagnostics.Debug.WriteLine(T.Name);
                            if (T.Name == "ResXResourceReader") rr = T;
                            if (T.Name == "ResXResourceWriter") rw = T;
                        }
                    }
                }
                System.Diagnostics.Debug.WriteLine(((Type)rr).AssemblyQualifiedName);
                System.Diagnostics.Debug.WriteLine(((Type)rw).AssemblyQualifiedName);


    ça m'affiche ça :

    System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
    System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089

    Demain, il reste à creuser la syntaxe d'appel.

    Je regarderai si ça, ça aide :

    https://msdn.microsoft.com/fr-fr/library/a89hcwhh(v=vs.110).aspx

    • Modifié Gloops lundi 3 avril 2017 16:26
    lundi 3 avril 2017 16:07
  • Bon, apparemment, il manque encore quelque chose.

    J'ai donc ajouté :

    	ConstructorInfo ConstRr = ((Type)rr).GetConstructor(Type.EmptyTypes);
    	ConstructorInfo ConstRw = ((Type)rw).GetConstructor(Type.EmptyTypes);
    	Object[] ListArg = new Object[1];
    	string strChemin = PathRessGlob(NomObjet, strCult);
    	ListArg[0] = strChemin;
    	Object Rr1 = ConstRr.Invoke(ListArg);
    
    	Object Rw1 = ConstRw.Invoke(ListArg);
    
    	Rr1.AddResource("cle", "texte");

    Et ... Rr1 contient bien la copie d'un objet ResXResourceReader, mais le souci est qu'il est de type objet, et que le type rr n'est pas reconnu pour un cast, donc le compilateur me dit que le type objet n'a pas de méthode AddResource.

    Comment y a-t-il lieu d'effectuer ce typage ?

    J'ai essayé ça

    (((Type)rw)Rw1).

    mais bien sûr quand je tape le point l'intellisense ne me propose rien.

    • Modifié Gloops mardi 4 avril 2017 09:26
    mardi 4 avril 2017 09:20
  • La réflexion m'a donné plus de fil à retordre que prévu.

    Finalement, j'en ai eu pour moins de deux heures à implémenter moi-même un ResXResourceWriter pour le web, après avoir effectué la lecture dans le code de la DataGrid, mais le ResXResourceReader pourrait être implémenté sur le même principe.

    Je n'ai mis là-dedans que ce que j'utilise, il n'y a donc pas tous les membres du ResXResourceWriter traditionnel de System.Windows.Forms, mais il y a moyen de créer des ressources texte dans un fichier de ressource au chemin donné en argument. Si le fichier existe déjà, une exception est levée au moment de l'enregistrement, et les ressources sauvegardées dans un fichier temporaire dont le nom a été noté lors de l'ouverture. Attention je me base sur un fichier de ressource vide, SourceRessource.xml, qui se trouve dans le répertoire App_Data, comme il est facile à obtenir (en l'ouvrant en mode texte) je ne le reproduis pas ici.

    Le message d'erreur apparaît en Français, c'est un point qu'on peut améliorer.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Xml;
    using System.Xml.Linq;
    using System.IO;
    
    namespace GestionRessources
    {
        public class ResXResourceWriter
        {
            
            private XmlDocument _xDoc = null;
            private XmlNode _root = null;
            private string _strPath = null;
            private string _strPathErr = null;
    
            public XmlDocument XDoc
            {
                get
                {
                    return _xDoc;
                }
            }
    
            public XmlNode Root
            {
                get
                {
                    return _root;
                }
    
            }
            
            public string PathOfFile
            {
                get
                {
                    return _strPath;
                }
            }
    
            public ResXResourceWriter(string strFilePath)
            {
                _strPath = strFilePath;
                string strPathSourceXml = HttpContext.Current.Server.MapPath(@"~\App_Data\SourceRessource.xml");
                _xDoc = new XmlDocument();
                if(File.Exists(_strPath))
                {
                    _strPathErr = Path.Combine(Path.GetDirectoryName(strFilePath), (Path.GetRandomFileName() + ".resx"));
                    strFilePath = _strPathErr;
                }
                File.Copy(strPathSourceXml, strFilePath);
                XDoc.Load(strFilePath);
                _root = XDoc.DocumentElement ;
    
            }
    
            public bool AddResource(string NomRessource, string Contenu)
            {
                AddResource(NomRessource, Contenu, "");
                return true;
            }
    
            public bool AddResource(string NomRessource, string Contenu, string Commentaire)
            {
                XmlElement nod = XDoc.CreateElement(string.Empty, "data", string.Empty);
                XmlAttribute att = XDoc.CreateAttribute("name");
                att.Value = NomRessource;
                nod.Attributes.Append(att);
                att = XDoc.CreateAttribute("xml:space");
                att.Value = "preserve";
                nod.Attributes.Append(att);
    
                XmlElement el = XDoc.CreateElement(string.Empty, "value", string.Empty);
                el.InnerText = Contenu;
    
                nod.AppendChild(el);
    
                if(!String.IsNullOrEmpty(Commentaire))
                {
                    XmlElement elC = XDoc.CreateElement(string.Empty, "comment", string.Empty);
                    elC.InnerText = Commentaire;
                    nod.AppendChild(elC);
                }
    
                Root.AppendChild(nod);
    
                return true;
            }
    
            public void Close()
            {
    
                try
                {
                    if (String.IsNullOrEmpty(_strPathErr))
                    {
                        XDoc.Save(_strPath);
                    }
                    else
                    {
                        XDoc.Save(_strPathErr);
                    }
                }
                catch(Exception ex)
                {
                    throw ex;
                }
                if (!String.IsNullOrEmpty(_strPathErr))
                {
                    throw new Exception(String.Format("Fichier <br /><i>{0}</i> <br /><br />déjà existant, sauvegarde effectuée sous <br /><br /><i>{1}</i>", _strPath, _strPathErr));
                }
            }
    
    
        }
    }


    Exemple de procédure appelante :

            protected void Button1_Click(object sender, EventArgs e)
            {
    
                try
                {
                    ResXResourceWriter ResX = new ResXResourceWriter(@"C:\Users\bibi\documents\visual studio 2013\Projects\GestionRessources\GestionRessources\App_GlobalResources\Resource2.resx");
                    foreach (EltRessource elt in GestionRessources.App_Code.Param.LstEntree)
                    {
                        ResX.AddResource(elt.NomRessource, elt.Traduction, elt.CommentaireTraduction);
                    }
                    lblReponse.Text = "Sauvegarde effectuée sous " + ResX.PathOfFile;
                    ResX.Close();
                }
                catch(Exception ex)
                {
                    lblReponse.Text = ex.Message;
                    lblReponse.ForeColor = System.Drawing.Color.Red;
                }
                Button1.Visible = false;
            }
        }

    Ah, oui, vous avez vu que je me suis basé sur une classe décrivant une ressource, qui s'appelle EltRessource ; j'ai aussi créé une classe statique Param où je stocke une copie de la liste de ressources.

    Voici EltRessource :

    using System;
    using System.Data;
    using System.Configuration;
    using System.Web;
    using System.Web.Security;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Web.UI.WebControls.WebParts;
    using System.Web.UI.HtmlControls;
    using System.Collections.Generic;
    using System.Xml.Linq;
    using System.Diagnostics;
    using System.Xml;
    using System.Data;
    
    
    namespace GestionRessources
    {
    
        /// <summary>
        /// Description résumée de EltRessource
        /// </summary>
        /// <exclude/>
        public class EltRessource
        {
            /// <summary>
            ///
            /// </summary>
            /// <param name="Nom"></param>
            /// <param name="ValeurInitiale"></param>
            /// <param name="Commentaire"></param>
            public EltRessource(string Nom, string ValeurInitiale, string Commentaire)
            {
                _NomRessource = Nom;
                _Valeur = ValeurInitiale;
                _Comment = Commentaire;
            }
    
            public EltRessource()
            {
    
            }
    
            private string _NomRessource;
    
            private string _Valeur;
    
            private string _Comment;
    
            private string _Traduction;
    
            private string _CommentaireTraduction;
    
    
            /// <summary>
            ///
            /// </summary>
            /// <exclude />
            public string Comment
            {
                get { return _Comment; }
                set { _Comment = value; }
            }
    
            /// <summary>
            ///
            /// </summary>
            /// <exclude />
            public string Valeur
            {
                get { return _Valeur; }
                set { _Valeur = value; }
            }
    
            /// <summary>
            ///
            /// </summary>
            /// <exclude />
            public string NomRessource
            {
                get { return _NomRessource; }
                set { _NomRessource = value; }
            }
    
            public string Traduction
            {
    
                get { return _Traduction; }
    
                set { _Traduction = value; }
            }
    
            public string CommentaireTraduction
            {
                get { return _CommentaireTraduction; }
                set { _CommentaireTraduction = value; }
            }
    
            public Object GetContent()
            {
                if (GestionRessources.App_Code.Param.LstEntree == null)
                {
                    List<EltRessource> LstEntree = new List<EltRessource>();
                    XmlDocument X = new XmlDocument();
                    string strPath = @"C:\Users\bibi\Documents\visual studio 2013\Projects\GestionRessources\GestionRessources\App_GlobalResources\Resource1.resx";
                    X.Load(strPath);
                    XmlNodeList Contenu = X.SelectNodes("root/data");
                    foreach (XmlNode nod in Contenu)
                    {
                        string Nom = null;
                        string ValeurInitiale = null;
                        string Commentaire = null;
                        Debug.Print("{0} : {1}", nod.Attributes["name"].Value, nod.SelectSingleNode("value").InnerText);
                        Nom = nod.Attributes["name"].Value;
                        ValeurInitiale = nod.SelectSingleNode("value").InnerText;
                        if (nod.SelectNodes("comment").Count > 0)
                        {
                            Debug.Print(nod.SelectSingleNode("comment").InnerText);
                            Commentaire = nod.SelectSingleNode("comment").InnerText;
                        }
                        EltRessource Elt = new EltRessource(Nom, ValeurInitiale, Commentaire);
                        LstEntree.Add(Elt);
                    }
    
                    GestionRessources.App_Code.Param.LstEntree = LstEntree;
    
                    return LstEntree;
                }
                else
                {
                    return GestionRessources.App_Code.Param.LstEntree;
                }
            }
    
            public Object Edit(string inNomRessource, string inTraduction)
            {
                List<GestionRessources.EltRessource> LstEntree = GestionRessources.App_Code.Param.LstEntree;
                EltRessource Sel = null;
                foreach(EltRessource Elt in LstEntree)
                {
                    if(Elt.NomRessource.Equals(inNomRessource))
                    {
                        Sel = Elt;
                    }
                }
                Sel.Traduction = inTraduction;
                return true;
            }
    
            private static bool Trouve(EltRessource o, string inNomRessource)
            {
                return o.NomRessource.Equals(inNomRessource);
            }
    
        }
    }

    Et, en sortant un peu du sujet, j'ai noté que sous Visual Studio 2013 (c'est valable à partir du 2012), après avoir créé une classe dans App_Code, il faut, dans ses propriétés, modifier l'attribut "Action de génération" en "Compiler" plutôt que "Contenu", sinon la classe n'est pas reconnue dans le code.





    • Marqué comme réponse Gloops jeudi 6 avril 2017 12:25
    • Modifié Gloops jeudi 6 avril 2017 12:43
    jeudi 6 avril 2017 12:24
  • Puisqu'aussi bien un peu plus loin dans le projet j'ai aussi eu besoin d'un ResXResourceReader, le voilà (toujours le même principe : il n'y a que la partie dont j'ai eu besoin).

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Xml;
    
    namespace GestionRessources
    {
        public class ResXResourceReader
        {
            private XmlDocument _xDoc = null;
            private XmlNode _root = null;
            private string _strPath = null;
            private string _strPathErr = null;
    
            private Dictionary<string, string> Contents = new Dictionary<string, string>();
            private Dictionary<string, string> Comments = new Dictionary<string, string>();
    
            public ResXResourceReader(string strFilePath)
            {
                _xDoc = new XmlDocument();
                _xDoc.Load(strFilePath);
                foreach(XmlNode nod in _xDoc.SelectNodes("root/data"))
                {
                    string NomRessource = nod.Attributes["name"].Value;
                    string ValeurInitiale = nod.SelectSingleNode("value").InnerText;
                    string Commentaire = "";
                    if (nod.SelectNodes("comment").Count > 0)
                    {
                        //Debug.Print(nod.SelectSingleNode("comment").InnerText);
                        Commentaire = nod.SelectSingleNode("comment").InnerText;
                    }
    
                    Contents.Add(NomRessource, ValeurInitiale);
                    Comments.Add(NomRessource, Commentaire);
                }
            }
    
            public string GetContent(string inNomRessource)
            {
                return Contents[inNomRessource];
            }
    
            public string GetComment(string inNomRessource)
            {
                return Comments[inNomRessource];
            }
        
        }
    }

    vendredi 7 avril 2017 15:40