begin process at 2012 02 11 17:53:44
  Trouver un code source :
 
dans
 
Accueil > 

Code

 > 

.NET

 > CRÉATION DYNAMIQUE D'OBJETS

CRÉATION DYNAMIQUE D'OBJETS


 Information sur la source

Note :
Aucune note
Catégorie :.NET Source .NET ( DotNet ) Classé sous :dynamique, reflection, plugins Niveau :Initié Date de création :19/02/2007 Date de mise à jour :20/02/2007 15:53:21 Vu / téléchargé :9 577 / 532

Auteur : Warny

Ecrire un message privé
Site perso
Commentaire sur cette source (10)
Ajouter un commentaire et/ou une note

 Description

Ce code sert à lire dans un répertoire l'ensemble des DLL et à les ajouter si elles correspondent à une interface ou dérivent d'un type donné.
J'utilise pour cela la reflexion.
Ceci peut permettre de créer des plugins.
La solution est composée de 3 projets, un executable qui contient le code de recherche des DLL, une DLL qui contient de type de référence (référencé dans l'exe) et une DLL qui contient les types dérivés (inconnue de l'exe).
Une propriété statique de la classe de base peut servir de clef, sinon, c'est le nom de la classe qui aura cette fonction.

Source

  • class Loader<BaseClass>
  • {
  • private Dictionary<string, Type> creatable;
  • private Type BaseType;
  • private string KeyElement;
  • private string defaultElement;
  • #region constructeurs
  • /// <summary>
  • /// Créé un chargeur de classe
  • /// </summary>
  • public Loader() : this("") { ;}
  • /// <summary>
  • /// Créé un chargeur de classes
  • /// </summary>
  • /// <param name="KeyElement">Element servant de clef</param>
  • public Loader(string KeyElement)
  • {
  • this.BaseType = typeof(BaseClass);
  • this.KeyElement = KeyElement;
  • creatable = new Dictionary<string,Type>();
  • }
  • #endregion
  • #region gestion des types
  • /// <summary>
  • /// Ajoute toutes les classes contenues dans toutes les assemblies d'un répertoire
  • /// </summary>
  • /// <param name="Path">Chemin Contenant les assemblies à charger</param>
  • public void AddFolder(string Path) {
  • //Charge les fichiers contenus dans le répertoire
  • DirectoryInfo directory = new DirectoryInfo(Path);
  • foreach (FileInfo file in directory.GetFiles("*.dll"))
  • {
  • AddAssembly(file.FullName);
  • }
  • }
  • /// <summary>
  • /// Ajoute toutes les classes contenues dans une assembly
  • /// </summary>
  • /// <param name="Path"></param>
  • public void AddAssembly(string Path)
  • {
  • //Charge l'assembly
  • Assembly assembly = Assembly.Load(AssemblyName.GetAssemblyName(Path)); ;
  • //Récupère tous les type contenus
  • Type[] types = assembly.GetTypes();
  • foreach (Type type in types)
  • {
  • AddType(type);
  • }
  • }
  • /// <summary>
  • /// Ajoute un type
  • /// </summary>
  • /// <param name="type">Type à ajouter</param>
  • private void AddType(Type type)
  • {
  • //Vérifie que le type dérive bien de la classe de base
  • if (!IsBasedOn(type,BaseType)) return;
  • //Récupère la valeur clef (nom de la classe si le nom est null)
  • string key;
  • if (string.IsNullOrEmpty(KeyElement)) {
  • key = type.FullName;
  • } else {
  • key = type.InvokeMember(KeyElement, BindingFlags.InvokeMethod | BindingFlags.FlattenHierarchy | BindingFlags.GetProperty | BindingFlags.Static | BindingFlags.Public, null, null, null).ToString();
  • }
  • //inscrit la classe dans la liste
  • creatable[key] = type;
  • }
  • /// <summary>
  • /// Ajoute un type
  • /// </summary>
  • /// <param name="Path">Chemin de l'assembly contenant la classe</param>
  • /// <param name="ClassName">Nom de la classe</param>
  • private void AddType(string Path, string ClassName)
  • {
  • //Charge l'assembly
  • Assembly assembly = Assembly.Load(AssemblyName.GetAssemblyName(Path));
  • //charge le type particulier
  • Type type = assembly.GetType(ClassName);
  • //Ajoute le type
  • AddType(type);
  • }
  • /// <summary>
  • /// Retire un type de la liste
  • /// </summary>
  • /// <param name="Id">Clef du type à enlever</param>
  • public void RemoveType(string Id)
  • {
  • creatable.Remove(Id);
  • }
  • #endregion
  • #region divers
  • /// <summary>
  • /// Défini une classe par défaut si la classe recherchée n'existe pas
  • /// </summary>
  • public string DefaultElement
  • {
  • get { return defaultElement; }
  • set { defaultElement = value; }
  • }
  • /// <summary>
  • /// Vérifie si une classe est basée ou dérivée d'un type particulier
  • /// </summary>
  • /// <param name="TestType">Type à tester</param>
  • /// <param name="BaseType">Référence</param>
  • /// <returns></returns>
  • private bool IsBasedOn(Type TestType, Type BaseType) {
  • if (TestType.IsSubclassOf(BaseType)) return true;
  • if (TestType.FullName == BaseType.FullName) return true;
  • if (Type.Equals(TestType, typeof(System.Object))) return false;
  • return IsBasedOn(TestType.BaseType, BaseType);
  • }
  • #endregion
  • #region creation de types
  • /// <summary>
  • /// Créé une instance de l'élément demandé, s'il n'existe pas, créé une instance de l'élément par défaut.
  • /// </summary>
  • /// <param name="Id">Identifiant de l'élément à créer</param>
  • /// <param name="parameters">Paramètres du constructeur</param>
  • /// <returns>Objet de la classe de base</returns>
  • public BaseClass Create(string Id, params object[] parameters)
  • {
  • object Obj;
  • try {
  • Obj = Activator.CreateInstance(creatable[Id], parameters);
  • } catch {
  • try {
  • Obj = Activator.CreateInstance(creatable[defaultElement], parameters);
  • } catch {
  • throw new System.Reflection.ReflectionTypeLoadException(null, null, "Impossible de créer l'objet, la clef n'existe pas");
  • }
  • }
  • return (BaseClass)Obj;
  • }
  • #endregion
  • }
class Loader<BaseClass> 
{
    private Dictionary<string, Type> creatable;
    private Type BaseType;
    private string KeyElement;
    private string defaultElement;

    #region constructeurs

    /// <summary>
    /// Créé un chargeur de classe
    /// </summary>
    public Loader() : this("") { ;}

    /// <summary>
    /// Créé un chargeur de classes
    /// </summary>
    /// <param name="KeyElement">Element servant de clef</param>
    public Loader(string KeyElement)
    {
        this.BaseType = typeof(BaseClass);
        this.KeyElement = KeyElement;
        creatable = new Dictionary<string,Type>();
    }

    #endregion

    #region gestion des types
    /// <summary>
    /// Ajoute toutes les classes contenues dans toutes les assemblies d'un répertoire
    /// </summary>
    /// <param name="Path">Chemin Contenant les assemblies à charger</param>
    public void AddFolder(string Path) {
        //Charge les fichiers contenus dans le répertoire
        DirectoryInfo directory = new DirectoryInfo(Path);
        foreach (FileInfo file in directory.GetFiles("*.dll"))
        {
            AddAssembly(file.FullName);
        }
    }

    /// <summary>
    /// Ajoute toutes les classes contenues dans une assembly
    /// </summary>
    /// <param name="Path"></param>
    public void AddAssembly(string Path)
    {
        //Charge l'assembly
        Assembly assembly = Assembly.Load(AssemblyName.GetAssemblyName(Path)); ;
        //Récupère tous les type contenus
        Type[] types = assembly.GetTypes();
        foreach (Type type in types)
        {
            AddType(type);
        }
    }

    /// <summary>
    /// Ajoute un type
    /// </summary>
    /// <param name="type">Type à ajouter</param>
    private void AddType(Type type)
    {
        //Vérifie que le type dérive bien de la classe de base
        if (!IsBasedOn(type,BaseType)) return;
        //Récupère la valeur clef (nom de la classe si le nom est null)
        string key;
        if (string.IsNullOrEmpty(KeyElement)) {
            key = type.FullName;
        } else {
            key = type.InvokeMember(KeyElement, BindingFlags.InvokeMethod | BindingFlags.FlattenHierarchy | BindingFlags.GetProperty | BindingFlags.Static | BindingFlags.Public, null, null, null).ToString();
        }
        //inscrit la classe dans la liste
        creatable[key] = type;
    }

    /// <summary>
    /// Ajoute un type
    /// </summary>
    /// <param name="Path">Chemin de l'assembly contenant la classe</param>
    /// <param name="ClassName">Nom de la classe</param>
    private void AddType(string Path, string ClassName)
    {
        //Charge l'assembly
        Assembly assembly = Assembly.Load(AssemblyName.GetAssemblyName(Path));
        //charge le type particulier
        Type type = assembly.GetType(ClassName);
        //Ajoute le type
        AddType(type);
    }

    /// <summary>
    /// Retire un type de la liste
    /// </summary>
    /// <param name="Id">Clef du type à enlever</param>
    public void RemoveType(string Id)
    {
        creatable.Remove(Id);
    }   
    #endregion

    #region divers
    /// <summary>
    /// Défini une classe par défaut si la classe recherchée n'existe pas
    /// </summary>
    public string DefaultElement
    {
        get { return defaultElement; }
        set { defaultElement = value; }
    }

    /// <summary>
    /// Vérifie si une classe est basée ou dérivée d'un type particulier
    /// </summary>
    /// <param name="TestType">Type à tester</param>
    /// <param name="BaseType">Référence</param>
    /// <returns></returns>
    private bool IsBasedOn(Type TestType, Type BaseType) {
        if (TestType.IsSubclassOf(BaseType)) return true;
        if (TestType.FullName == BaseType.FullName) return true;
        if (Type.Equals(TestType, typeof(System.Object))) return false;
        return IsBasedOn(TestType.BaseType, BaseType);
    }

    #endregion

    #region creation de types
    /// <summary>
    /// Créé une instance de l'élément demandé, s'il n'existe pas, créé une instance de l'élément par défaut.
    /// </summary>
    /// <param name="Id">Identifiant de l'élément à créer</param>
    /// <param name="parameters">Paramètres du constructeur</param>
    /// <returns>Objet de la classe de base</returns>
    public BaseClass Create(string Id, params object[] parameters)
    {
        object Obj;
        try {
            Obj = Activator.CreateInstance(creatable[Id], parameters);
        } catch {
            try {
                Obj = Activator.CreateInstance(creatable[defaultElement], parameters);
            } catch {
                throw new System.Reflection.ReflectionTypeLoadException(null, null, "Impossible de créer l'objet, la clef n'existe pas");
            }
        }
        return (BaseClass)Obj;
    }

    #endregion
}


 Fichier Zip

Les Membres Club peuvent télécharger directement un fichier contenu dans le zip sans télécharger le zip en entier !
  •   TestDynamique
    •   BaseBibliotheque
    •   TestBibliotheque
      •   bin
        •   Debug
          • BaseBibliotheque.dllTélécharger ce fichier [Réservé aux membres club]16 384 octets
          • BaseBibliotheque.pdbTélécharger ce fichier [Réservé aux membres club]11 776 octets
          • TestBibliotheque.dllTélécharger ce fichier [Réservé aux membres club]16 384 octets
          • TestBibliotheque.pdbTélécharger ce fichier [Réservé aux membres club]15 872 octets
      •   obj
        •   Debug
          •   Refactor
            • TestBibliotheque.dllTélécharger ce fichier [Réservé aux membres club]16 384 octets
          • TempPE
          • ResolveAssemblyReference.cacheTélécharger ce fichier [Réservé aux membres club]2 744 octets
          • TestBibliotheque.dllTélécharger ce fichier [Réservé aux membres club]16 384 octets
          • TestBibliotheque.pdbTélécharger ce fichier [Réservé aux membres club]15 872 octets
        • TestBibliotheque.csproj.FileList.txtTélécharger ce fichier [Réservé aux membres club]Voir ce fichier234 octets
      •   Properties
      • ClassDiagram1.cdTélécharger ce fichier [Réservé aux membres club]1 040 octets
      • CTest1.csTélécharger ce fichier [Réservé aux membres club]Voir ce fichier358 octets
      • CTest2.csTélécharger ce fichier [Réservé aux membres club]Voir ce fichier356 octets
      • CTest3.csTélécharger ce fichier [Réservé aux membres club]Voir ce fichier243 octets
      • TestBibliotheque.csprojTélécharger ce fichier [Réservé aux membres club]Voir ce fichier2 351 octets
    •   TestDynamique
    • TestDynamique.slnTélécharger ce fichier [Réservé aux membres club]Voir ce fichier2 178 octets
    • TestDynamique.suoTélécharger ce fichier [Réservé aux membres club]23 040 octets

Télécharger le zip


 Historique

20 février 2007 07:46:37 :
Prise en compte des remarques de bidou
20 février 2007 15:53:21 :
Correction d'erreur

 Sources du même auteur

Source avec Zip PREPAREDFORMAT
Source avec Zip Source .NET (Dotnet) CLASSE XMLMAPPER
Source avec Zip Source avec une capture Source .NET (Dotnet) T-SQL FORMATER
Source avec Zip Source avec une capture UTILITAIRES DE DÉCODAGE ET D'ENCODAGE
Source .NET (Dotnet) GREP POUR WINDOWS

 Sources de la même categorie

Source avec Zip Source avec une capture Source .NET (Dotnet) ORIONBANQUE par toutphp
Source avec Zip Source avec une capture Source .NET (Dotnet) ORIONAPPLICATION par toutphp
Source avec Zip SOCKET CONNEXION CLIENT & SERVEUR par ziedto83
Source avec Zip Source .NET (Dotnet) FFMPEG.NET : WRAPPER .NET DE FFMPEG par MasterShadows
Source avec Zip Source .NET (Dotnet) ATTACHER, CRÉER ET SAUVEGARDER UNE BASE DE DONNÉES SQL SERVE... par Alvepinai

 Sources en rapport avec celle ci

Source avec Zip Source avec une capture Source .NET (Dotnet) ORIONAPPLICATION par toutphp
Source avec Zip Source avec une capture Source .NET (Dotnet) DÉMINEUR JR par jrscofield
Source avec Zip Source .NET (Dotnet) SCRIPTS DE PILOTAGE REFLECTION 8 par Renfield
Source avec Zip PREPAREDFORMAT par Warny
Source avec Zip Source .NET (Dotnet) CLASSE XMLMAPPER par Warny

Commentaires et avis

Commentaire de Bidou le 19/02/2007 21:17:29 administrateur CS

Quelques remarques:

- Méthodes AddType(Type type) de Loads.cs
if(KeyElement.Lenght > 0) devrait plutôt être string.IsNullOrEmpty(KeyElement)

- Dans la même méthode:

if (creatable.ContainsKey(value))
{
   creatable[value] = type;
}
else
{
   creatable.Add(value, type);
}

peut-etre remplacé par

creatable[value] = type;


Si on passe une valeur inexistante dans le loader.Create, le program bug. Il faut faire un teste dans la méthode qui fait le CreateInstance (si je ne spécifie pas defaultElement, il est null => plantage)
Autre chose, 'value' est un mot clef, c'est pas recommandé de l'utiliser comme nom de variable.

Sinon pour la création des Plugins, je me demande si c'est pas plus indiqué de passer par des interfaces plutôt que Reflexion...
A voir.

Commentaire de Warny le 20/02/2007 07:44:35

Merci pour tes remarques, je vais mettre en place une vraie exception dans le createinstance (le plantage est voulu). Pour le test d'existence, il est indispensable.

Sinon, pour la création des plugins, il est clair que des interfaces c'est bien, mais certains objets ont parfois une activité dont on ne peut pas se passer. Même dans ce cas, il faut pouvoir charger ces objets, si on doit tout recompiler, ce n'est pas très interressant, c'est l'utilité de mon programme.
L'idée de base était de reprendre ma source client DNS et de pouvoir l'étendre à l'envie en rajoutant des extensions sans modifier le programme de base comme je dois le faire aujourd'hui.
Or, pour celle-ci, je reçois un numéro de service que je dois interpréter. Comme je ne vais pas utiliser le numéro de service pour nommer mes classes (mais bien le nom du service) il fallait que je trouve une solution... la voici.

Commentaire de sebmafate le 20/02/2007 09:39:57 administrateur CS

Question purement "esthétique", pourquoi écrire :
    public Loader() : this("") { ;}

Alors qu'il suffit d'écrire :
    public Loader() : this("") { }

Commentaire de Bidou le 20/02/2007 10:06:57 administrateur CS

"Pour le test d'existence, il est indispensable."
Non, tu peux bel et bien faire le remplacement que j'ai indiqué plus haut, simplement: creatable[value] = type;
L'indexeur se charge de tout...

Commentaire de Warny le 20/02/2007 11:08:01

Bidou -> Après que tu me l'ais dit... j'ai testé, il est indispensable, si je n'utilise pas ces lignes de code l'objet n'est pas integré à ma collection.

Commentaire de Bidou le 20/02/2007 11:37:56 administrateur CS

Tu fais très certainement une erreur. Pour t'en rendre compte, tu peux donner un coup de Reflector. Pour l'indexeur tu trouves:

public void set_Item(TKey key, TValue value)
{
    this.Insert(key, value, false);
}


Commentaire de Warny le 20/02/2007 14:08:36

Je ne fais pas d'erreur. La méthode Insert existe sur la classe List et pas sur la classe Dictionary.

Commentaire de Bidou le 20/02/2007 14:35:32 administrateur CS

Mais noooooon, Insert est une méthode privée du Dictionnary, utilisée (entre autre) par l'indexeur.
Pour te convaincre que l'indexeur ajoute bien l'élément dans le dictionary, créer une application console et met ceci dedans :

            Dictionary<int, string> dic = new Dictionary<int, string>();
            dic[1] = "Okay";        // Count 1  1-Okay
            dic[2] = "Salut";       // Count 2  1-Okay 2-Salut
            dic[2] = "Teste";       // Count 2  1-Okay 2-Teste

Commentaire de Warny le 20/02/2007 15:54:47

Oups, tu as raison, l'erreur venait d'ailleurs dans mon code, c'est corrigé.

Commentaire de sebmafate le 20/02/2007 15:56:00 administrateur CS

:)

Bidou : 1, Warny : 0

J'adore ;)

 Ajouter un commentaire


Discussions en rapport avec ce code source dans le forum

Declaration dynamique d'une classe [ par Barz ] Comment par code peut-on executer une méthode d'une classe en dynamique, c'est à dire en ayant que une chaine correspondant au nom de la classe et une litse de fichiers dynamique [ par denistheisen ] Bonjour, Je suis a la recherche d'un javascript qui me permettrait de generer une liste dymanique de fichiers se trouvant dans un de mes repertoires e Création d'un tableau dynamique HTML par le code... [ par pchanet ] Bonjour à tous,Je suis en train de développer la gestion d'une table HTML (type &lt;table&gt;...&lt;/table&gt;) en dynamique à partir de la page de co Génération dynamique de windows.form en C# [ par Thanos_the_yopper ] Bonjour,je suis en train de faire une appli qui, en fonction du contenu d'un fichier XML construit dynamiquement une fenetre windows avec des champs d Objet dynamique .net. [ par jonguerre ] Bonjour,Petite question je crée 2 objets Panel (panel1,panel2);panel1 = new System.Windows.Forms.Panel();panel2 = new System.Windows.Forms.Panel();J'a Tableau dynamique [ par redpooka ] Comment faire un tableau à 2 dimension dynamique ?Avec les collections arraylist, on peut faire un mais c'est juste avec une dimension.tableau du styl Faire une zone de texte dynamique [ par typhoonx ] Bonjour,Je suis en train de programmer une application de compression (dll dévelopée en C) et interface C#.Je voudrais faire une zone de texte dans la site Dynamique [ par Gina78 ] Bonjour,Je voudrais juste savoir les premières étapes pour creer un site DynamiqueMerci générer un contrôle ( bouton) dynamique en c# [ par poelvo ] Je voudrais créer des boutons à partir d'une liste d'objet d'une base de données, je n'aurai donc jamais le même nombre de boutons. Je ne sais donc pa Nom dynamique de fichier [ par Sunnyprog ] Sunnyprogfont=GeorgiaBonjour tt le monde !je voudrais savoir comment faire pour nommer un fichier de telle manière qu'il ait pour nom le contenu d'une


Nos sponsors


Sondage...

Comparez les prix

CalendriCode

Février 2012
LMMJVSD
  12345
6789101112
13141516171819
20212223242526
272829    

Consulter la suite du CalendriCode

Photothèque

 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 0,702 sec (4)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales