[C#] Parcours de tous les controles d'une application ?

Parcours de tous les controles d'une application ? [C#] - C#/.NET managed - Programmation

Marsh Posté le 01-04-2008 à 15:30:18    

Hello,
 
je vous explique un peu le contexte.
L'idée est de simplifier la vie du développeur.
 
Exemple:
 
Générer automatiquement la hierarchie d'une application dans la base de données à partir des Menu présents dans les forms (et page).
Ceci nécessite un parcourt de tous les controles de l'application.
Sauf qu'à l'heure actuel, je ne sais faire un parcourt que d'une form courante.
Il est évidemment probablement qu'une form non instanciée contienne un menu et que je dois également récupérer ce dernier.
 
Alors ma question est simple, comment faire ça (si c'est possible) ?
 
Autre idée, à chaque fois que je "drag'n drop" un menu sur une form, j'enregistre un lien vers cet objet dans un control global de l'application (en mode design).
L'idéal serait d'avoir juste à parcourir les menus stockés dans ce contrôle pour récupérer leur contenu et mettre à jour la base de données.
 
Et là non plus, je ne vois pas comment faire, car les élements n'étant pas instanciés ça coince...
 
Merci pour votre aide  :hello:

Reply

Marsh Posté le 01-04-2008 à 15:30:18   

Reply

Marsh Posté le 01-04-2008 à 19:20:46    

Application.GetOpenForms() ou un truc du genre, te retourne une collection des forms ouvertes de ton programme.
 
Si tu veux les forms contenues dans ton assembly, alors il faut les trouver via ce moyen.
Sauf qu'après, je vois pas ce que tu veux en faire, vu que tu peux très bien avoir dans ton code "this.Controls.Add(new Label());" par exemple... (typiquement le cas pour les membres d'un menustrip par exemple)
 

Code :
  1. // Récupération de toutes les "forms" de l'application
  2.            Assembly asm = Assembly.GetExecutingAssembly();
  3.  
  4.            // Parcours de tous les types de l'assembly
  5.            foreach (Type t in asm.GetTypes())
  6.            {
  7.                // Il s'agit d'une form
  8.                if (t.BaseType == typeof(Form))
  9.                {
  10.                    MessageBox.Show(t.Name);
  11.                }
  12.            }


Message édité par MagicBuzz le 01-04-2008 à 19:21:31
Reply

Marsh Posté le 01-04-2008 à 20:06:19    

Et ce code fonctionne aussi si le type se trouve dans une DLL importée en référence ?
 
Je t'explique un peu le pourquoi de ma demande.
 
Techniquement, on a développé un module de sécurité où l'on attribue des droits sur des actions (qui se trouvent dans les applications).
Seulement, cela implique de créer les actions dans le module de sécurité, et à la longue c'est très lourd et chiant à gérer (notamment pour le développeur).
 
L'idéal serait que le développeur développe normalement, c'est à dire, mets ses MenuStrip, ToolbarStrip dans ses forms, et qu'au moment du login au début de l'application, ça va récupérer tous ses menus et vérifier si la hiérarchie de l'application est à jour dans la base de données. Si c'est pas le cas, on met à jour la BDD.
 
En gros, avoir une génération automatique de la hiérarchie de l'application dans la base de données sans avoir à se casser le cul dans le module de sécurité à ajouter les rubriques et les actions une à une.
 
Si ce n'est pas clair, dis moi, je ré-expliquerai ;)

Reply

Marsh Posté le 01-04-2008 à 20:15:04    

nucl3arfl0 a écrit :

Et ce code fonctionne aussi si le type se trouve dans une DLL importée en référence ?
 
Je t'explique un peu le pourquoi de ma demande.
 
Techniquement, on a développé un module de sécurité où l'on attribue des droits sur des actions (qui se trouvent dans les applications).
Seulement, cela implique de créer les actions dans le module de sécurité, et à la longue c'est très lourd et chiant à gérer (notamment pour le développeur).
 
L'idéal serait que le développeur développe normalement, c'est à dire, mets ses MenuStrip, ToolbarStrip dans ses forms, et qu'au moment du login au début de l'application, ça va récupérer tous ses menus et vérifier si la hiérarchie de l'application est à jour dans la base de données. Si c'est pas le cas, on met à jour la BDD.
 
En gros, avoir une génération automatique de la hiérarchie de l'application dans la base de données sans avoir à se casser le cul dans le module de sécurité à ajouter les rubriques et les actions une à une.
 
Si ce n'est pas clair, dis moi, je ré-expliquerai ;)


Tu peux récupérer les referenced assemblies de l'assembly courrante, donc je dirais que oui (à condition que tu places ce code dans l'assembly "racine" )

Reply

Marsh Posté le 01-04-2008 à 21:55:04    

MagicBuzz a écrit :


Tu peux récupérer les referenced assemblies de l'assembly courrante, donc je dirais que oui (à condition que tu places ce code dans l'assembly "racine" )


Oki merci, je testerai ça demain.... misère misère quand même...  :pt1cable:

Reply

Marsh Posté le 02-04-2008 à 09:44:19    

Hello,
 
bon ça marche en Win (à part si on ajoute des items via le code source et non plus via le mode design), par contre en Web, niet :/

Reply

Marsh Posté le 02-04-2008 à 12:07:05    

T'as bien changé le test en :

Code :
  1. if (t.BaseType == typeof(WebForm))


:whistle:

Reply

Marsh Posté le 02-04-2008 à 12:30:14    

Code :
  1. private void findCalendar()
  2.     {
  3.         Assembly asm = Assembly.GetExecutingAssembly();
  4.         foreach (Type t in asm.GetTypes())
  5.         {
  6.             if (t.BaseType == typeof(Page))
  7.             {
  8.                 findCalendarHelper((Page)Activator.CreateInstance(t));
  9.             }
  10.         }
  11.     }
  12.     private void findCalendarHelper(Page p)
  13.     {
  14.         foreach (Control c in p.Controls)
  15.         {
  16.             if (c is Page)
  17.                 findCalendarHelper((Page)c);
  18.             else
  19.             {
  20.                 if (c.GetType() == typeof(Calendar))
  21.                 {
  22.                     Response.Write("<script language=\"JavaScript\">alert('"+c.ID+"');</script>" );
  23.                 }
  24.             }
  25.         }
  26.     }


 
Calendar c'est un exemple évidemment.
Je veux récupérer toutes mes pages, et dans ces pages, je veux récupérer les controles.
Par contre, je pense que ma façon de procéder là, n'est pas bonne. Du moins, il ne faudrait pas que j'utilise Activator.CreateInstance sur le type page.
Une idée ?

Reply

Marsh Posté le 03-04-2008 à 09:26:22    

J'ai bloqué là dessus aussi.
 
J'ai pas trouvé comment rechercher les contrôles contenus dans une classe lorsque cette dernière n'est pas instanciée.
 
Avec la réflection, j'ai tenté d'aller voir les Properties et les Attributes des pages, mais rien trouvé. Pourtant je pense que c'est plutôt cette piste qu'il faut suivre.
 
D'un autre côté, créer une instance, c'est garantir d'avoir sous la main les contrôles y compris ceux créés avec des "this.Controls.Add()"
 
Bonne chance en tout cas :sweat:

Reply

Marsh Posté le 03-04-2008 à 12:13:15    

MagicBuzz a écrit :

J'ai bloqué là dessus aussi.
 
J'ai pas trouvé comment rechercher les contrôles contenus dans une classe lorsque cette dernière n'est pas instanciée.
 
Avec la réflection, j'ai tenté d'aller voir les Properties et les Attributes des pages, mais rien trouvé. Pourtant je pense que c'est plutôt cette piste qu'il faut suivre.
 
D'un autre côté, créer une instance, c'est garantir d'avoir sous la main les contrôles y compris ceux créés avec des "this.Controls.Add()"
 
Bonne chance en tout cas :sweat:


Merci.
 
Je me suis renseigné sur le forum MSDN US, et quelqu'un a donné la même idée que j'avais au départ:
 
Parcourir le code source toutes les pages ASPX et récupérer le code "balisé" du contrôle..
Là également, ça pose problème dans le cas d'un menu généré dynamiquement, mais bon, c'est mieux que rien, et ça a l'air de marcher. Quant au temps d'exécution, ça ne se passera qu'au niveau du développeur, donc aucune incidence pour le client.
 
Merci Microsoft qui nous pousse à programmer comme des cochons  :(  
 
Edit: Quant à la reflection, c'était une piste pour le Win, car quand on glisse et dépose le composant dans la form, VS sauvegarde les informations dans le désigner. Ce qui fait que quand tu instancies la form dynamiquement, tu peux récupérer ces attributs.
En revanche, pour le web, ce n'est pas possible. Quand on glisse et dépose le composant dans la page, c'est uniquement le code ASP qui est généré. Et dans ce cas là, l'objet n'est instancié qu'au runtime avec ses attributs.
Et comme dans la reflection tu dois lui passer le type pour l'instanciation, ta page n'hérite que de la classe "System.Web.UI.Page", et cette instanciation te donne qu'une page vierge sans attributs...

Message cité 1 fois
Message édité par nucl3arfl0 le 03-04-2008 à 12:16:46
Reply

Marsh Posté le 03-04-2008 à 12:13:15   

Reply

Marsh Posté le 03-04-2008 à 17:57:05    

nucl3arfl0 a écrit :


Merci.
 
Je me suis renseigné sur le forum MSDN US, et quelqu'un a donné la même idée que j'avais au départ:
 
Parcourir le code source toutes les pages ASPX et récupérer le code "balisé" du contrôle..
Là également, ça pose problème dans le cas d'un menu généré dynamiquement, mais bon, c'est mieux que rien, et ça a l'air de marcher. Quant au temps d'exécution, ça ne se passera qu'au niveau du développeur, donc aucune incidence pour le client.
 
Merci Microsoft qui nous pousse à programmer comme des cochons  :(
 
Edit: Quant à la reflection, c'était une piste pour le Win, car quand on glisse et dépose le composant dans la form, VS sauvegarde les informations dans le désigner. Ce qui fait que quand tu instancies la form dynamiquement, tu peux récupérer ces attributs.
En revanche, pour le web, ce n'est pas possible. Quand on glisse et dépose le composant dans la page, c'est uniquement le code ASP qui est généré. Et dans ce cas là, l'objet n'est instancié qu'au runtime avec ses attributs.
Et comme dans la reflection tu dois lui passer le type pour l'instanciation, ta page n'hérite que de la classe "System.Web.UI.Page", et cette instanciation te donne qu'une page vierge sans attributs...


 
[:ofou] c'est l'hopital qui se fout de la charité là, avec l'usine à gaz que tu veux monter ;)


---------------
VA APPRENDRE ET REVIENS QUAND TU SAIS, SINON ABSTIENT TOI C'EST UN GRAND CONSEIL QUE JE TE DONNE... TU ES INCOMPÉTENT ET C'EST UNE RÉALITÉ, TU N'AS RIEN A FAIRE ICI FAUT S'Y CONNAITRE ... -Jojo1998 - RIP - http://tinyurl.com/qc47ftk
Reply

Marsh Posté le 03-04-2008 à 19:23:46    

Moi je me base sur les contraintes qu'on me donne :(
Vaut mieux avoir une usine à gaz qui fonctionne que rien du tout :o
Ah et j'ai déjà retourné le problème en long en large et en travers, j'peux pas faire mieux, le reste ne dépendant pas de moi..

Reply

Marsh Posté le 03-04-2008 à 23:30:58    

Un truc pas trop crade serait j'imagine quelquechose de ce genre :
 
Projet "Web Control Collection" :

Code :
  1. using System;
  2. using System.Xml;
  3. using System.Web.UI;
  4. using System.Web.UI.WebControls;
  5. using System.ComponentModel;
  6.  
  7. namespace SecurityControls
  8. {
  9.    public class SecurityManager
  10.    {
  11.        public bool CheckVisible(WebControl wc)
  12.        {
  13.            bool display = true;
  14.            XmlDocument dom = new XmlDocument();
  15.            dom.Load(wc.Page.MapPath("rights.xml" ));
  16.            XmlNode ControlSecurity = dom.DocumentElement.SelectSingleNode("control[@id='" + wc.ID + "' and @page='" + wc.Page.AppRelativeVirtualPath + "']" );
  17.            if (ControlSecurity == null) ControlSecurity = dom.DocumentElement.SelectSingleNode("control[@id='" + wc.ID + "' and not(@page)]" );
  18.            if (ControlSecurity != null)
  19.            {
  20.                display = bool.Parse(ControlSecurity.Attributes["display"].Value);
  21.            }
  22.            if (!display) return false;
  23.            return true;
  24.        }
  25.    }
  26.  
  27.    /// <summary>
  28.    /// Summary description for SecurizedControls
  29.    /// </summary>
  30.    [DefaultProperty("Text" ), ToolboxData("<{0}:SecurizedLabel runat='server'></{0}:SecurizedLabel>" )]
  31.    public class SecurizedLabel : Label
  32.    {
  33.        SecurityManager sm;
  34.        public SecurizedLabel()
  35.        {
  36.            sm = new SecurityManager();
  37.        }
  38.  
  39.        protected override void Render(System.Web.UI.HtmlTextWriter writer)
  40.        {
  41.            if (!sm.CheckVisible(this)) return;
  42.            base.Render(writer);
  43.        }
  44.    }
  45.  
  46.    /// <summary>
  47.    /// Summary description for SecurizedControls
  48.    /// </summary>
  49.    [DefaultProperty("Text" ), ToolboxData("<{0}:SecurizedTextBox runat='server'></{0}:SecurizedTextBox>" )]
  50.    public class SecurizedTextBox : TextBox
  51.    {
  52.        SecurityManager sm;
  53.        public SecurizedTextBox()
  54.        {
  55.            sm = new SecurityManager();
  56.        }
  57.  
  58.        protected override void Render(System.Web.UI.HtmlTextWriter writer)
  59.        {
  60.            if (!sm.CheckVisible(this)) return;
  61.            base.Render(writer);
  62.        }
  63.    }
  64. }


 
Projet "Web Site", référençant le premier :

Code :
  1. <%@ Page Language="C#" AutoEventWireup="true"  CodeFile="Default.aspx.cs" Inherits="_Default" %>
  2.  
  3. <%@ Register Assembly="SecurizedWebControls" Namespace="SecurityControls" TagPrefix="cc1" %>
  4.  
  5. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  6.  
  7. <html xmlns="http://www.w3.org/1999/xhtml" >
  8. <head runat="server">
  9.    <title>Untitled Page</title>
  10. </head>
  11. <body>
  12.    <form id="form1" runat="server">
  13.        <cc1:SecurizedLabel ID="SecurizedLabel1" runat="server">Test</cc1:SecurizedLabel>
  14.        <br />
  15.        <cc1:SecurizedTextBox ID="SecurizedTextBox1" runat="server">Test</cc1:SecurizedTextBox>
  16.        <br />
  17.        <cc1:SecurizedLabel ID="SecurizedLabel2" runat="server">Test</cc1:SecurizedLabel>
  18.        <br />
  19.        <cc1:SecurizedTextBox ID="SecurizedTextBox2" runat="server">Test</cc1:SecurizedTextBox>
  20.        <br />
  21.        <cc1:SecurizedLabel ID="SecurizedLabel3" runat="server">Test</cc1:SecurizedLabel>
  22.        <br />
  23.        <cc1:SecurizedTextBox ID="SecurizedTextBox3" runat="server">Test</cc1:SecurizedTextBox>
  24.    </form>
  25. </body>
  26. </html>


+ default.aspx.cs tout vide chez moi
 

Code :
  1. <?xml version="1.0" encoding="utf-8" ?>
  2. <controls>
  3.     <control id="SecurizedLabel1" display="false"/>
  4.     <control id="SecurizedLabel2" display="true"/>
  5.     <control id="SecurizedLabel2" display="false" page="~/default.aspx"/>
  6.     <control id="SecurizedTextBox1" display="false"/>
  7.     <control id="SecurizedTextBox2" display="true"/>
  8. </controls>


J'ai ça à la racinde de mon site
 
Et ça me permet, via mon fichier XML de décider quels champs s'affichent ou non, en prenant le pas sur ce que je peux tenter de vouloir faire au niveau programmation dans la page.

Reply

Marsh Posté le 03-04-2008 à 23:33:20    

Mais bon, ça nécessite quand même quelques changements dans le code existant, et surtout, ça n'empêche pas un développeur d'utiliser les contrôles standards plutôt que ceux-ci.

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed