Instance d'une classe a partir du nom

Fermé
Beetlejuice722 Messages postés 70 Date d'inscription lundi 1 août 2005 Statut Membre Dernière intervention 7 septembre 2013 - 28 oct. 2008 à 15:06
 JapanFlag - 6 janv. 2010 à 15:21
Bonjour à tous,

A travers un projet de développement C#, je dispose actuellement d'une classe mère "Article", de sa classe fille "ArticleAcheté" et d'une classe "Program", distincte des 2 autres, celle-ci regroupe l'ensemble des actions possibles (lister, ajouter, modifier, supprimer, rechercher...) applicables sur les enregistrements (articles)

Ainsi, je souhaiterai dans la classe program pouvoir instancier un objet dont la classe serait fournit en paramètre à ma méthode dans une variable string...
--> exemple :
------------------------------------------------------------------
string nomClass = "ArticleAcheté";
static public void LISTER (string nomClass)
{
nomClass toto = new nomClass();
....
}
------------------------------------------------------------------
Ainsi, l'objet "toto" devrait ainsi pouvoir disposer de tout les attributs et methodes spécifiques à la classe fille "ArticleAcheté". De cette manière, on pourrait apeller toutes les methodes de la classe fille "ArticleAcheté" comme ceci :
toto.lecture();
ou encore toto.écriture(); etc...

De toute évidence, la syntaxe ou manière de faire que j'ai employé dans mon "exemple" ne fonctionne pas!

Par conséquent, j'espere que quelqu'un parmi vous pourra m'orienter dans cette réflexion, afin de résoudre ce problème...

Je vous en remercie par avance...

12 réponses

guillaume_74 Messages postés 111 Date d'inscription samedi 18 octobre 2008 Statut Membre Dernière intervention 29 juillet 2010 22
19 avril 2009 à 02:14
si t'es en .NET
ya la méthode "CallByName"

sinon...
lol la réflection! ca existe dans tout les langage ( dans les IDE, c'est ce qui permet l'intellisense: quand tu tape sur '.' ca te met des methode et tout et tout...)
1
Beetlejuice722 Messages postés 70 Date d'inscription lundi 1 août 2005 Statut Membre Dernière intervention 7 septembre 2013 61
28 oct. 2008 à 17:36
Personne n'aurait déja rencontré ce problème ?!

Je reste ouvert à toutes suggestions à venir...

Merci
0
Marco la baraque Messages postés 996 Date d'inscription vendredi 9 mai 2008 Statut Contributeur Dernière intervention 5 novembre 2009 328
28 oct. 2008 à 20:51
Bonsoir,
Regarde au niveau de l'API de réflexion : https://emerica.developpez.com/dotnet/reflection/introduction/csharp/

Perso je ne connais absolument pas le C# et je n'ai pas compris grand chose, mais si tu connais un peu le langage ça devrait aller.

Cordialement,
0
Beetlejuice722 Messages postés 70 Date d'inscription lundi 1 août 2005 Statut Membre Dernière intervention 7 septembre 2013 61
28 oct. 2008 à 20:53
SVP, personne ne s'y connait dans cette notion ?!

mon ami Google m'a dis qu'il fallait mettre en place un principe apellé la "reflection" qui est spécifique aux languages managés...

Je parviens à créer mon objet selon les différentes manières de faire indiqués par des developpeurs, mais dans la mise en oeuvre, mon objet est bien créer, mais il semble ne pas être l'instance de la classe voulue que je lui indique, puiske
les méthodes et attributs de cette classe ne lui sont pas applicables !

Voici donc les différents resultats, je n'ai juska présent pas réussit à mettre en place :

http://www.codyx.org/snippet_instancier-classe-partir-son-nom_95.aspx
https://www.developpez.net/forums/d90451/dotnet/langages/csharp/csharp-instancier-objet-partir-d-string/
https://forum.hardware.fr/hfr/Programmation/CNET-managed/creer-instance-connaissant-sujet_48018_1.htm
https://www.generation-nt.com/reponses/instancier-une-classe-par-son-nom-entraide-2367051.html

Help me please...
0
Beetlejuice722 Messages postés 70 Date d'inscription lundi 1 août 2005 Statut Membre Dernière intervention 7 septembre 2013 61
28 oct. 2008 à 22:05
Merci pour ton aide Marco...

je connais déja ce tuto de developpez.com
Il est bien trop généraliste et effectivement assez compliqué dans le principe à comprendre...

Me concernant, il ne s'agit que de quelques lignes de codes pour permettre la creation d'un objet directement relié aux méthodes et attributs d'une classe fille

Le problème est que l'objet est bien créer mais il ne dispose que de 4 méthodes "génériques" fournient par le compilateur (Equals, getHashCode, getType, toString) qui ne sont en aucun cas spécifique à la classe dont il est question (afficher, get, set, lecture)...
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Marco la baraque Messages postés 996 Date d'inscription vendredi 9 mai 2008 Statut Contributeur Dernière intervention 5 novembre 2009 328
28 oct. 2008 à 22:32
Hello,
Je ne connais pas du tout le C#, mais grosso modo, tes classes sont définies dans des fichiers dll non ?
Du moins c'est ce que je crois comprendre d'après ce que je lis.

Cordialement,
0
guillaume_74 Messages postés 111 Date d'inscription samedi 18 octobre 2008 Statut Membre Dernière intervention 29 juillet 2010 22
28 oct. 2008 à 23:17
Je ne connais pas le C#
mais ça ressemble a du Java...
moi moi, ça ne marche pas du tout ton truc c'est normal... c'est pas du tout les mêmes types (après, ptètre des truc a la microsoft... va savoir^^ )
ArticleAchete article;
static public void LISTER (ArticleAchete articl)
{
articl= new ArticleAchete();
....
}

moi, je ne vois que ça de possible... bref^^ je n'ai surement pas comprit ton problème^^
0
Beetlejuice722 Messages postés 70 Date d'inscription lundi 1 août 2005 Statut Membre Dernière intervention 7 septembre 2013 61
28 oct. 2008 à 23:57
En fait, le but de la manoeuvre consiste exactement à déclarer un objet comme tu le fait, sauf que le paramètre en entrée de la méthode doit être une variable string, laquelle contient le nom de la classe pour laquelle sera déclarée l'instance...

cad, le nom de la classe ne doit pas être explicitement nommé, mais plutot contenu dans une chaine de caractère...
ex :
string maClasse = "ArticleAcheté";

static public void (string maClasse)
{
maClasse toto = new maClasse();
}

--> De toute évidence, l'instruction "maClasse toto = new maClasse();" est fausse et ne marche pas, car on ne peut pas convertir implicitement un string en un type (ou class)...

Le but est donc, de créer ou d'instancier un objet d'une classe dont le nom serait fournit dans une variable string (dispo en paramètre de la méthode) !!

Le problème réside uniquement dans la mise en oeuvre...
Ce procédé permet uniquement de rendre les éléments plus "modulaires"...
Imagine que l'on dispose de 100 classe fille pour la classe mère Article (un peu com en framework), cela voudrait dire qu'il faudrait faire autant de méthode lister qu'il y aurait de classe fille !!! Ce n'est pas gérable...

Dans tout les cas, je te suis très reconnaissant pour ton aide et pour ton soutien...
merci beaucoup ! :-)
0
choubaka Messages postés 39375 Date d'inscription jeudi 4 avril 2002 Statut Modérateur Dernière intervention 14 avril 2024 2 100
29 oct. 2008 à 07:24
en java, il existe une méthode "forName("String className), c'est une méthode statque de la classe Class.

mais en C#, jamais vu.

Beau petit challenge

j'ai trouvé ça

http://www.codyx.org/snippet_instancier-classe-partir-son-nom_95.aspx
0
Beetlejuice722 Messages postés 70 Date d'inscription lundi 1 août 2005 Statut Membre Dernière intervention 7 septembre 2013 61
29 oct. 2008 à 11:04
Bonjours,

Merci pour ton aide choubaka...

Effectivement, concernant la méthode forName en Java, je n'ai pas retrouvé d'équivalent en C#

Je te remercie également pour le petit tuto que tu m'a donné...
Mais je le connaissaisait déja (voir message 3 de ce topic), je parvient à le mettre en place !

Le problème est que l'objet est bien créer mais il ne dispose que de 4 méthodes "génériques" fournient par le compilateur (Equals, getHashCode, getType, toString) qui ne sont en aucun cas spécifique à la classe dont il est question (afficher, get, set, lecture, etc...) : il s'agit des méthodes que j'ai créer...

Le point obscur dans ce tuto (comme dans tout ceux du message 3), c'est de définir le rôle de l'assembly
Pourtant, je me suis déja documenté sur ce point précis de la "reflection" en C#, mais je ne parvient toujours pas à saisir la manière de faire !

Le but, est d'appeler le bon constructeur de la classe (spécifiée dans la variable string nomClass) passé en paramètre à la méthode, puis de pouvoir invoquer toutes les méthodes de la classe en question, à travers l'objet instancier (de cette même classe)

Le nom de la classe ne doit pas être explicitement nommé dans cette méthode (en dehors d'une variable string, qui lui est fournie en paramètre), car sinon cela impliquerait autant de redondance de code qu'il y aurait d'objet à déclarer pour chaque classe fille !

Une fois de + Merci de votre aide !
0
choubaka Messages postés 39375 Date d'inscription jeudi 4 avril 2002 Statut Modérateur Dernière intervention 14 avril 2024 2 100
29 oct. 2008 à 14:22
0
Beetlejuice722 Messages postés 70 Date d'inscription lundi 1 août 2005 Statut Membre Dernière intervention 7 septembre 2013 61
29 oct. 2008 à 19:08
Oui mais ici, le problème c'est qu'il faut nommer la classe fille explicitement...

Hors dans mon cas d'utilisation, le nom de la classe à instancier (à travers un objet), doit être contenu dans une variable string...

Si je fait comme dans le lien , j'obtient quelque chose comme :

Class2 c2 = (Class2)Type.GetType("ConsoleApplication1.Class2")....

Hors "Class2" indique et désigne clairement le nom de la classe fille à instancier pour l'objet c2...
Le problème réside justement dans le fait, que le nom ne doit apparaitre que dans une variable string, qui serait fournit en paramètre de la méthode appelante !

J'ai fouiller a plein d'endroit sur Google (developez, csharp, codyx, forum.hardware, génération...)
A chaque fois que c'est le même problème : cad, je me retrouve obligé de lui indiquer le nom de ma classe fille pour que mon objet puisse accéder à ses méthodes et attributs...

En java, ils utilisent une instruction class.forname() pour justement récuperer le contenu d'un string et le convertir...
Mais je ne vois toujours aucun équivalent "direct" en C#

Je suis sur ce problème depuis samedi dernier, et en dépit de ma persévérance, je commence un peu à désespérer...

En tout cas, merci de m'aider Choubaka !
0
Marco la baraque Messages postés 996 Date d'inscription vendredi 9 mai 2008 Statut Contributeur Dernière intervention 5 novembre 2009 328
29 oct. 2008 à 20:19
Hello,
Tu as peut-être déjà lu cet article :
https://www.generation-nt.com/reponses/besoin-d-explication-sur-la-reflexion-entraide-2347231.html

Je comprends effectivement de ne pas expliciter le type d'objet que tu crées, et pour cela tu dois impérativement utiliser le polymorphisme. La bonne solution est d'utiliser des interfaces (comme le montre cet exemple). De cette manière, le programme est totalement générique et te permet d'instancier toutes les classes qui implémentent ton interface.

"Et pour les autres?". Bah pour les autres, c'est moins évident. Tu peux surement caster ton objet dans une superclasse (par exemple en java tous les objets héritent de Object). Ainsi tu pourras manipuler tous tes objets. L'inconvénient de cette méthode, c'est que pour utiliser les méthodes spécifiques à ton objet, tu devras obligatoirement le downcaster (et donc il te faut connaitre le type de ton instance, en Java ça doit se faire avec obj.getClass()).

Mais bon, en pratique, tu utiliseras pratiquement toujours une interface car si dans ton code tu veux appeler une méthode spécifique, alors cela signifie que tu connais cette méthode, et tu sais que ton objet implémente telle interface (ou étend telle classe).

Cordialement,
0
tu chercherais pas tout simplement un truc du genre par hasard? C'est un petit extrait de ma classe Core...

private function includeModel($file)
{
$class = ucfirst($file);
$path = root .'model/'. $class .'.php';

if(file_exists($path))
{
require_once($path);
$Object = new $class();
$action = $this->vars['action'];
$Object->$action();
return true;
}
else return false;
}
0
Salut a tous :)

Je tenais a savoir si tu avais résolu ton problème BeetleJuice722 car je suis dans le même cas que toi pour un de mes projets. Après avoir errer sur le net pendant des heures, je n'ai toujours pas trouvé de solutions :s

Si tu n'as pas réussi, comment l'a tu esquivé ? :)

Merci d'avance de ta réponse ;)
0
Smashingraph
20 avril 2009 à 16:56
Bonjour à tous,

Je vois qu'il n'y a pas eu de réponses claires sur la question.

Pour créer un objet à l'aide la reflection, c'est très simple, tu récupères l'objet assembly, puis tu invoques "CreateInstance". A l'aide du nom de la classe et du tableau de paramètres passés (pour les arguments du constructeur), tu reçois un objet instancié de la classe voulue.

Voici ci-dessous 3 méthodes qui permettent d'effectuer ce traitement (la troisième est celle qui appelle "CreateInstance" sur l'objet Assembly):

1) Cette méthode récupère l'objet assembly de celle qui est en cours d'exécution. Typiquement si cette méthode se trouve dans une libraire externe à ton programme principal, l'assembly appelante (CallingAssembly) est la libraire externe, et donc cette méthode va instancier un objet d'une classe se trouvant dans la librairie externe. Elle appelle ensuite la méthode "CreateObject", troisième méthode ci-dessous.
public static object CreateObjectWithExecutingAssembly(string sClassName, object[] args)
{
    System.Reflection.Assembly oAssembly = System.Reflection.Assembly.GetExecutingAssembly();
     return CreateObject(sClassName, oAssembly, args);
}


2) Cette méthode récupère l'objet assembly de celle qui appelle cette methode. Typiquement si cette méthode se trouve dans une libraire externe à ton programme principal, l'assembly appelante (CallingAssembly) est
le programme principal, et donc cette méthode va instancier un objet d'une classe se trouvant dans ton programme principal (Partant du principe que ta librairie externe n'as aucune référence sur le programme principal). Elle appelle ensuite la méthode "CreateObject", troisième méthode ci-dessous.
 
public static object CreateObjectWithCallingAssembly(string sClassName, object[] args )
{
    System.Reflection.Assembly oAssembly = System.Reflection.Assembly.GetCallingAssembly();
    return CreateObject(sClassName, oAssembly, args);
}



3) Cette méthode va instancier un nouvel objet à l'aide de la String "sClassName" passée en paramètre. Les arguments correspondent à la signature du constructeur de la classe, à savoir les paramètres qu'il faut passer au constructeur.
public static object CreateObject(string sClassName,  System.Reflection.Assembly oAssembly, object[] args )
{
    return oAssembly.CreateInstance(sClassName, true, System.Reflection.BindingFlags.CreateInstance, null, args, null, null);
}


Ensuite, que faire avec cette objet ? Si on sait de quelle nature il doit être, il suffit de le caster dans l'objet voulu:
MaClasse oMaClasse = (MaClasse) objetInstancié;


Par contre si on ne connaît pas la nature de la classe, et qu'on a les méthode que l'on désire appeller sur cet objet sous forme de String (pour une application totalement dynamique, dont les indications sont écrites dans un fichier xml par exemple) il va falloir opérer comme ceci:

        public static object GetMethodObjectResult(object oUnderlyingObject, string sMethod, object[] oParams)
        {
            object oResult = null;
            System.Reflection.MethodInfo oMethodInfo = null;
            try
            {
                if (oUnderlyingObject != null)
                {
                    System.Type dynClassType = oUnderlyingObject.GetType();
                    if (sMethod != null && sMethod != "")
                    {
                        oMethodInfo = dynClassType.GetMethod(sMethod);
                        if (oMethodInfo != null)
                        {
                            oResult = oMethodInfo.Invoke(oUnderlyingObject, oParams);
                        }
                    }
                }
            }
            catch (Exception e)
            {
                // Exception à traiter au cas par cas
            }
            return oResult;
        }


Il ne reste plus qu'à traiter la réponse de la méthode, qui est sous forme d'un objet à caster selon le type.

Voilà j'espère avoir été plus ou moins clair, et j'espère que cela a pu éclairer certaines personnes.

Bonne fin de journée,
0
Type lObjType = Type.GetType("MaClasseACreer");
if
(lObjType != null)
{
Object lObject = Activator.CreateInstance(lObjType);
if
(lCmd != null)
{
....................................
}
}
0
MasterTnT > MasterTnT
24 avril 2009 à 14:09
il faut remplacer lCmd != null par lObject != null
0
La mèthode de http://www.codyx.org/snippet_instancier-classe-partir-son-nom_95.aspx est bien fo juste faire un cast après pour utiliser les autres methodes
0