Afficher un arbre dans la console

Nous avons vu comment récupérer les informations d'une classe et nous pouvons réutiliser notre fichier ClassInfo.cs, qui nous propose une classe avec une méthode qui nous retourne un tableau de TreeNodes.

Il nous suffit d'ajouter un fichier (Program.cs) qui comportera une méthode Main (le point d'entrée dans l'application).

Nous allons demander à l'utilisateur d'introduire un nom complet de fichier exécutable ou d'une dll, puis nous allons faire appel à notre classe ClassInfo pour récupérer un tableau qui contiendra les arbres à afficher.

La partie qui nous intéresse est la suivante :


Code c# (Program.cs getInfos()) (5 lignes) :
  1. TreeNode[] infos = ClassInfo.getInfos(filePath);
  2. foreach (TreeNode info in infos)
  3. {
  4. Console.Write(getSubInfos(info, 0));
  5. }

Nous allons donc créer une autre méthode pour récupérer les informations des arbres :


Code c# (Program.cs getSubInfos(TreeNode tn,int level)) (20 lignes) :
  1. private static String getSubInfos(TreeNode tn,int level)
  2. {
  3. StringBuilder str = new StringBuilder();
  4. if (tn != null)
  5. {
  6. for (int i = 0; i < level; i++)
  7. {
  8. str.Append("\t");
  9. }
  10. str.Append(tn.Text);
  11. str.Append("\n");
  12. level++;
  13. foreach (TreeNode n in tn.Nodes)
  14. {
  15. str.Append(getSubInfos(n, level));
  16. }
  17. }
  18. else str.Append("Error (Null Argument)");
  19. return str.ToString();
  20. }

Cette méthode est récursive. C'est à dire qu'elle s'appelle elle-même, comme une série de poupées russes. Comme chaque nœud de l'arbre peut être considéré comme un arbre, nous voyons l'intérêt d'une telle méthode.

Remarques

Pour que notre classe Program puisse utiliser la classe ClassInfo, nous pouvons les placer dans le même espace de noms en plaçant le code dans namespace ClassExplorer{}.

Comme nous travaillons avec des TreeNodes, nous devons utiliser System.Windows.Forms.
Si nous travaillons avec Visual Studio, il est possible que nous ne puissions pas ajouter la directive using System.Windows.Forms; et elle peut ne pas être présente dans l'onglet Solution Explorer.
Si nous rencontrons ce problème, nous pouvons ajouter manuellement la référence : dans le menu Project, nous devons sélectionner Add Reference, puis sélectionner System.Windows.Forms dans les références.
Si cette opération ne permet toujours pas d'utiliser la classe TreeNode, nous devons fermer le projet, puis l'ouvrir à nouveau, ou simplement cliquer dans l'onglet Solution Explorer sur le bouton Refresh.

Si nous désirons effectuer des tests sur le nom de fichier introduit, nous devons ajouter using System.IO; afin de pouvoir utiliser les classes FileSystemInfo et FileInfo.

Résultat

Nous pouvons encore décorer notre console avec des couleurs selon le niveau dans l'arbre, et nous pouvons ajouter une méthode pour afficher les erreurs.

Voici donc ce que donne l'affichage des TreeNodes dans la console.

Affichage des TreeNodes dans la console

Code complet

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using System.Windows.Forms;
  5. using System.IO;
  6. namespace ClassExplorer
  7. {
  8. class Program
  9. {
  10. public static void Main(string[] args)
  11. {
  12. Console.WriteLine("CLASS EXPLORER\n");
  13. getInfos();
  14. Console.WriteLine("\n\nPress Enter to exit...");
  15. Console.Read();
  16. }
  17. private static void getSubInfos(TreeNode tn, int level)
  18. {
  19. if (!tn.ForeColor.Name.Equals("0"))
  20. {
  21. try
  22. {
  23. Console.ForegroundColor = (ConsoleColor)Enum.Parse(typeof(ConsoleColor), tn.ForeColor.Name);
  24. }
  25. catch (ArgumentException e)
  26. {
  27. Console.ForegroundColor = ConsoleColor.Gray;
  28. }
  29. }
  30. else Console.ForegroundColor = ConsoleColor.Gray;
  31. if (tn != null)
  32. {
  33. for (int i = 0; i < level; i++)
  34. {
  35. Console.Write("\t");
  36. }
  37. Console.Write(tn.Text);
  38. Console.Write("\n");
  39. level++;
  40. foreach (TreeNode n in tn.Nodes)
  41. {
  42. getSubInfos(n, level);
  43. }
  44. }
  45. else displayError("Argument may not be null");
  46. }
  47. private static void displayError(String error)
  48. {
  49. Console.ForegroundColor = ConsoleColor.White;
  50. Console.BackgroundColor = ConsoleColor.Red;
  51. Console.WriteLine("ERROR :\n" + error);
  52. Console.ForegroundColor = ConsoleColor.Gray;
  53. Console.BackgroundColor = ConsoleColor.Black;
  54. }
  55. private static void getInfos()
  56. {
  57. Console.Write("Enter File Path : ");
  58. String filePath = Console.ReadLine();
  59. if(filePath!=null && filePath!="")
  60. {
  61. FileSystemInfo f = new FileInfo(filePath);
  62. if (!f.Exists)
  63. {
  64. displayError("\"" + filePath + "\" is not a valid file path");
  65. getInfos();
  66. }
  67. else if (f.Extension == ".exe" || f.Extension == ".dll")
  68. {
  69. TreeNode[] infos = ClassInfo.getInfos(filePath);
  70. foreach (TreeNode info in infos)
  71. {
  72. getSubInfos(info, 0);
  73. }
  74. }
  75. else
  76. {
  77. displayError("Wrong extension. Only exe and dll are allowed.");
  78. getInfos();
  79. }
  80. }
  81. else
  82. {
  83. displayError("You must enter something...");
  84. getInfos();
  85. }
  86. }
  87. }
  88. }
  1. using System;
  2. using System.Collections;
  3. using System.Text;
  4. using System.Reflection;
  5. using System.IO;
  6. using System.Windows.Forms;
  7. using System.Drawing;
  8. namespace ClassExplorer
  9. {
  10. class ClassInfo
  11. {
  12. public static TreeNode[] getInfos(String classPath)
  13. {
  14. TreeNode classesTreeNode = new TreeNode("Classes");
  15. TreeNode enumsTreeNode = new TreeNode("Enums");
  16. TreeNode interfacesTreeNode = new TreeNode("Interfaces");
  17. try
  18. {
  19. Assembly assembly = Assembly.LoadFrom(classPath);
  20. Type[] types = assembly.GetTypes();
  21. foreach (Type type in types)
  22. {
  23. if (type.IsClass) classesTreeNode.Nodes.Add(getClassNode(type));
  24. else if (type.IsEnum) enumsTreeNode.Nodes.Add(type.Name);
  25. else if (type.IsInterface) interfacesTreeNode.Nodes.Add(type.Name);
  26. }
  27. }
  28. catch (Exception e)
  29. {
  30. }
  31. TreeNode[] infos = { classesTreeNode, enumsTreeNode, interfacesTreeNode };
  32. return infos;
  33. }
  34. public static String getFileInfos(String classPath)
  35. {
  36. FileSystemInfo f = new FileInfo(classPath);
  37. StringBuilder str = new StringBuilder(f.Name);
  38. str.Append("\n\nInfos :");
  39. str.Append("\nCreation time : ");
  40. str.Append(f.CreationTime);
  41. str.Append("\nLast access : ");
  42. str.Append(f.LastAccessTime);
  43. str.Append("\nAttributes : ");
  44. str.Append(f.Attributes);
  45. str.Append("\nFullName : ");
  46. str.Append(f.FullName);
  47. return str.ToString();
  48. }
  49. public static String getFileName(String classPath)
  50. {
  51. FileSystemInfo f = new FileInfo(classPath);
  52. return f.Name;
  53. }
  54. private static TreeNode getClassNode(Type type)
  55. {
  56. TreeNode classNode = new TreeNode(type.Name);
  57. MethodInfo[] methodsInfos = type.GetMethods(
  58. BindingFlags.NonPublic |
  59. BindingFlags.Instance |
  60. BindingFlags.Public |
  61. BindingFlags.Static |
  62. BindingFlags.DeclaredOnly
  63. );
  64. if (methodsInfos.Length > 0)
  65. {
  66. TreeNode methodsNode = new TreeNode("Methods (" + methodsInfos.Length +")");
  67. methodsNode.ForeColor = System.Drawing.Color.Blue;
  68. foreach (MethodInfo methodInfo in methodsInfos)
  69. {
  70. methodsNode.Nodes.Add(getMethodNode(methodInfo));
  71. }
  72. classNode.Nodes.Add(methodsNode);
  73. }
  74. else classNode.Nodes.Add("No methods available");
  75. ConstructorInfo[] constructorsInfos = type.GetConstructors(
  76. BindingFlags.NonPublic |
  77. BindingFlags.Instance |
  78. BindingFlags.Public |
  79. BindingFlags.Static |
  80. BindingFlags.DeclaredOnly
  81. );
  82. if (constructorsInfos.Length > 0)
  83. {
  84. TreeNode constructorsNode = new TreeNode("Constructors (" + constructorsInfos.Length + ")");
  85. constructorsNode.ForeColor = System.Drawing.Color.Green;
  86. foreach (ConstructorInfo constructorInfo in constructorsInfos)
  87. {
  88. constructorsNode.Nodes.Add(getConstructorNode(constructorInfo));
  89. }
  90. classNode.Nodes.Add(constructorsNode);
  91. }
  92. else classNode.Nodes.Add("No constructors available");
  93. FieldInfo[] fieldsInfos = type.GetFields(
  94. BindingFlags.NonPublic |
  95. BindingFlags.Instance |
  96. BindingFlags.Public |
  97. BindingFlags.Static |
  98. BindingFlags.DeclaredOnly
  99. );
  100. if (fieldsInfos.Length > 0)
  101. {
  102. TreeNode fieldsNode = new TreeNode("Fields (" + fieldsInfos.Length + ")");
  103. fieldsNode.ForeColor = System.Drawing.Color.Navy;
  104. foreach (FieldInfo fieldInfo in fieldsInfos)
  105. {
  106. fieldsNode.Nodes.Add(getFieldNode(fieldInfo));
  107. }
  108. classNode.Nodes.Add(fieldsNode);
  109. }
  110. else classNode.Nodes.Add("No fields available");
  111. PropertyInfo[] propsInfos = type.GetProperties(
  112. BindingFlags.NonPublic |
  113. BindingFlags.Instance |
  114. BindingFlags.Public |
  115. BindingFlags.Static |
  116. BindingFlags.DeclaredOnly
  117. );
  118. if (propsInfos.Length > 0)
  119. {
  120. TreeNode propsNode = new TreeNode("Properties (" + propsInfos.Length + ")");
  121. foreach (PropertyInfo propInfo in propsInfos)
  122. {
  123. propsNode.Nodes.Add(propInfo.Name);
  124. }
  125. classNode.Nodes.Add(propsNode);
  126. }
  127. else classNode.Nodes.Add("No properties available");
  128. return classNode;
  129. }
  130. private static TreeNode getConstructorNode(ConstructorInfo constructorInfo)
  131. {
  132. StringBuilder constrStr = new StringBuilder();
  133. if (constructorInfo.IsPrivate) constrStr.Append("Private ");
  134. else if (constructorInfo.IsStatic) constrStr.Append("Static ");
  135. else if (constructorInfo.IsPublic) constrStr.Append("Public ");
  136. constrStr.Append(constructorInfo.Name);
  137. TreeNode constructorNode = new TreeNode(constrStr.ToString());
  138. constructorNode.ForeColor = System.Drawing.Color.GreenYellow;
  139. ParameterInfo[] paramInfos = constructorInfo.GetParameters();
  140. foreach (ParameterInfo paramInfo in paramInfos)
  141. {
  142. constructorNode.Nodes.Add(
  143. String.Format("{0} {1}", paramInfo.ParameterType.ToString(), paramInfo.Name)
  144. );
  145. }
  146. return constructorNode;
  147. }
  148. private static TreeNode getMethodNode(MethodInfo methodInfo)
  149. {
  150. StringBuilder methodStr = new StringBuilder();
  151. if (methodInfo.IsPrivate) methodStr.Append("Private ");
  152. else if (methodInfo.IsStatic) methodStr.Append("Static ");
  153. else if (methodInfo.IsPublic) methodStr.Append("Public ");
  154. methodStr.Append(methodInfo.Name);
  155. TreeNode methodNode = new TreeNode(methodStr.ToString());
  156. methodNode.ForeColor = System.Drawing.Color.Red;
  157. ParameterInfo[] paramInfos = methodInfo.GetParameters();
  158. foreach (ParameterInfo paramInfo in paramInfos)
  159. {
  160. methodNode.Nodes.Add(
  161. String.Format("{0} {1}", paramInfo.ParameterType.ToString(), paramInfo.Name)
  162. );
  163. }
  164. return methodNode;
  165. }
  166. private static TreeNode getFieldNode(FieldInfo fieldInfo)
  167. {
  168. StringBuilder fieldStr = new StringBuilder();
  169. if (fieldInfo.IsPrivate) fieldStr.Append("Private ");
  170. else if (fieldInfo.IsStatic) fieldStr.Append("Static ");
  171. else if (fieldInfo.IsPublic) fieldStr.Append("Public ");
  172. fieldStr.Append(fieldInfo.Name);
  173. TreeNode fieldNode = new TreeNode(fieldStr.ToString());
  174. fieldNode.ForeColor = System.Drawing.Color.DarkGreen;
  175. return fieldNode;
  176. }
  177. }
  178. }

Pourquoi avons nous placé la construction des différents arbres dans un bloc try? Simplement pour parer aux mauvaises manipulations de l'utilisateur du programme. Nous verrons dans les pages suivantes comment utiliser notre classe ClassInfo au travers d'une application graphique, mais dans le cas de l'utilisation par une application en mode console, l'utilisateur peut introduire un nom de fichier qui n'existe pas. Dans ce cas, une erreur de type FileNotFoundException est lancée.

Nous pouvons procéder de deux manières pour parer à ces erreurs :

  • Placer le code qui génère les arbres dans le modèle (la classe ClassInfo) dans un bloc try/catch
  • Tester la validité du fichier dans notre vue (la classe Program).

Dans ces codes, les deux types de contrôles sont présents.

Réseaux sociaux

Vous pouvez modifier vos préférences dans votre profil pour ne plus afficher les interactions avec les réseaux sociaux sur ces pages.

 

Nuage de mots clés

17 mots clés dont 0 définis manuellement (plus d'information...).

Avertissement

Cette page ne possède pas encore de mots clés manuels, ceci est donc un exemple automatique (les niveaux de pertinence sont fictifs, mais les liens sont valables). Pour tester le nuage avec une page qui contient des mots définis manuellement, vous pouvez cliquer ici.

Vous pouvez modifier vos préférences dans votre profil pour ne plus afficher le nuage de mots clés.

 

Astuce pour imprimer les couleurs des cellules de tableaux : http://www.gaudry.be/ast-rf-450.html
Aucun commentaire pour cette page

© Ce document issu de l′infobrol est enregistré sous le certificat Cyber PrInterDeposit Digital Numbertection. Enregistrement IDDN n° 5329-3668
Document créé le 01/10/06 11:54, dernière modification le Vendredi 17 Juin 2011, 12:11
Source du document imprimé : http:///www.gaudry.be/csharp-console-tree.html
St.Gaudry©07.01.02
Outils (masquer)
||
Recherche (afficher)
Recherche :

Utilisateur (masquer)
Apparence (afficher)
Stats (afficher)
15838 documents
455 astuces.
550 niouzes.
3107 definitions.
447 membres.
8121 messages.

Document genere en :
0,15 seconde

Mises à jour :
Mises à jour du site
Citation (masquer)
Le cœur est la source de toutes les erreurs dont nous avons besoin.

Bernard Fontenelle
 
l'infobrol
Nous sommes le Lundi 26 Juin 2017, 19:19, toutes les heures sont au format GMT+1.00 Heure, heure d'été (+1)