begin process at 2010 02 10 13:13:14
  Trouver un code source :
 
dans
 
Accueil > Forum > 

C#

 > 

Système

 > 

Exécution

 > 

Creation dynamique d'objet, InvalidCastException


Derniers messages déposésPoser une question dans le forum ou lancer une discussion

Creation dynamique d'objet, InvalidCastException

dimanche 18 février 2007 à 22:04:32 | Creation dynamique d'objet, InvalidCastException

Warny

Salut,

Je cherche à créer un chargeur de classe. Celui-ci doit me permettre de trouver les classes dans une assembly ou un ensemble d'assembly qui dérive d'une classe particulière. Ca, ça marche bien. Ensuite j'essaye d'instancier (grâce à une reflection) ces objets et de les caster dans mon type de base. Et là j'obtient une InvalidCastException.

En fait je sèche. Dans ma classe, les procédures importantes sont AddType (qui ajoute un type à la liste des types créables) et Create qui créé une instance d'un type. J'ai une procédure IsBasedOn qui renvoi true si un type dérive d'un autre (par implementation ou interface) et que j'utilise pour valider l'utilisation ou non d'une classe. L'erreur a lieu dans create alors que j'essaye de caster mon objet tout frais sorti du moule.

Merci d'avance de votre aide,
Olivier

Voici les bouts utiles de mon code :

class

Loader<BaseClass>

{

privateDictionary<string, Type> creatable;
privateType BaseType;
privatestring KeyElement;
privatestring 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 =
newDictionary<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>

publicvoid AddFolder(string Path) {

//Charge les fichiers contenus dans le répertoire
DirectoryInfo directory = newDirectoryInfo(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>

publicvoid AddAssembly(string Path) {

//Charge l'assembly
Assembly assembly = Assembly.LoadFrom(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>
privatevoid AddType(Type type) {

//Vérifie que le type dérive bien de la classe de base

if
(!IsBasedOn(type,BaseType)) return; // <----- Avec cette procédure, je suis sûr que les types dérivent de BaseClass

//Récupère la valeur clef (nom de la classe si le nom est null)
string value;
if (KeyElement.Length > 0) {

value = type.InvokeMember(KeyElement,

BindingFlags.InvokeMethod | BindingFlags.FlattenHierarchy | BindingFlags.GetProperty | BindingFlags.Static | BindingFlags.Public, null, null, null).ToString();

}

else {

value = type.FullName;

}

//inscrit la classe dans la liste

if (creatable.ContainsKey(value)) {

creatable[value] = type;

}

else {

creatable.Add(value, 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>
privatevoid AddType(string Path, string ClassName) {

//Charge l'assembly
Assembly assembly = Assembly.LoadFrom(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>
publicvoid 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>
publicstring 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>
privatebool IsBasedOn(Type TestType, Type BaseType) {

if (TestType.IsSubclassOf(BaseType)) returntrue;
if (TestType.FullName == BaseType.FullName) returntrue;
if (TestType.FullName == "System.Object") returnfalse;
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, paramsobject[] parameters) {

object Obj;
try {

Obj = creatable[Id].InvokeMember(

null, BindingFlags.CreateInstance | BindingFlags.Public | BindingFlags.FlattenHierarchy | BindingFlags.Instance, null, null, parameters);

}

catch {

Obj = creatable[defaultElement].InvokeMember(

null, BindingFlags.CreateInstance | BindingFlags.Public | BindingFlags.FlattenHierarchy | BindingFlags.Instance, null, null, parameters);

}

return (BaseClass)Obj; // <---- l'erreur a lieu ici, le cast est refusé alors que le type dérive bien

}

#endregion

}


Console.Out.WriteLine("Warny")
Il y a 10 types de personnes
Ceux qui comptent en binaire... et les autres
dimanche 18 février 2007 à 22:59:40 | Re : Creation dynamique d'objet, InvalidCastException

coq

Administrateur CodeS-SourceS
Salut,

Tu devrais vérifier tes retours avant de les utiliser. Après à voir mais je ne suis pas sur que FlattenHierarchy aie sa place ici.
Sinon jette un oeil à Activator.CreateInstance, ça devrait t'intéresser.



/*
coq
MVP Visual C#
CoqBlog
*/
lundi 19 février 2007 à 08:10:59 | Re : Creation dynamique d'objet, InvalidCastException

Warny

L'Activator.CreateInstance simplifie nettement la lecture du code mais n'arrange pas mon problème.
Comment vérifier mon retour ? J'ai essayé de rajouter un As BaseClass, mais le compilateur le refuse.

J'ai fait un test où toutes mes entrées sont valides (toutes les classes lues dérivent de BaseClass). Même quand j'essaye d'instancier baseClass, j'ai la même erreur (voici la copie du message, c'est un peu frustrant)

L'exception System.InvalidCastException n'a pas été gérée
  Message="Impossible d'effectuer un cast d'un objet de type 'BaseBibliotheque.Parent' en type 'BaseBibliotheque.Parent'."
  Source="TestDynamique"
  StackTrace:
       à AutoCreation.Loader`1.Create(String Id, Object[] parameters) dans c:\projets\TestDynamique\TestDynamique\Loader.cs:ligne 163
       à AutoCreation.Program.Main(String[] args) dans c:\projets\TestDynamique\TestDynamique\Program.cs:ligne 13
       à System.AppDomain.nExecuteAssembly(Assembly assembly, String[] args)
       à System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       à Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       à System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       à System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       à System.Threading.ThreadHelper.ThreadStart()


Console.Out.WriteLine("Warny")
Il y a 10 types de personnes
Ceux qui comptent en binaire... et les autres
lundi 19 février 2007 à 17:30:51 | Re : Creation dynamique d'objet, InvalidCastException

Warny

Réponse acceptée !
J'ai trouvé. Le problème vient d'un chargement partiel d'assembly voilà la solution :

A la place de
Assembly assembly = Assembly.LoadFrom(Path);

Il faut mettre
Assembly assembly = Assembly.Load(AssemblyName.GetAssemblyName(Path)); ;

Qui permet au framework de faire la correspondance dans le cache d'assembly entre celle qu'on charge et celles déjà chargées.

Console.Out.WriteLine("Warny")
Il y a 10 types de personnes
Ceux qui comptent en binaire... et les autres
mercredi 20 mai 2009 à 21:57:45 | Re : Creation dynamique d'objet, InvalidCastException

EmacLi

Un grand merci Warny ! :)


Cette discussion est classée dans : type, classe, assembly, bindingflags, creatable


Répondre à ce message

Sujets en rapport avec ce message

Problème de type avec une assembly [ par dinytro ] Bonjour, je souhaiterais récupérer le type d'une assembly que je charge avec la methode SampleAssembly = Assembly.LoadFrom(@pathAssembly); Ensuite je Assembly.GetInterfaces() [ par jusob ] Bonjour, J'ai un programme qui doit charger des DLLs. Ces DLLs implémentent l'interface PluginInterface. Programme principal: foreach (Type typ Chargement dynamique de type [ par thiosyiasar ] Bonjour a tous, Je voudrais faire un chargement dynamique d'assembly à partir d'un nom complet de type Par exemple, j'ai la valeur suivante "Syste Dll, arguments & classe utilisateur [ par MyXiLo ] Bonjour,Je voudrais passer un argument dérivant d'une classe utilisateur à une méthode d'une dll.J'ai un programme qui contient une classe MaClass et DTD Classe??? [ par Globinours ] J'aimerais générer une DTD à partir d'un TreeView mais là n'est pas le problème! En fait j'aimerais savoir si il existe une classe permettant d' écrir Accéder à une classe d’un autre assembly [ par Souliabdo ] Bonjour, J’ai une e solution qui contient deux projets, mon problème est que je n’arrive pas à accéder, depuis le projet de démarrage, aux classes d Initialisations "Array-like", IEnumerable, Add() et lecture seule [ par Minotthor ] Bonjour à tous, Soient Assembly et Sign, deux classes "maison" ... Je crée une classe Assembly qui contiendra en privé une List et j'aimerais pouvoi réutilisation de classes dans C# [ par happyleptic ] Bonjour,Je suis un habitué du C++, je m'essaye à C# en .Net.J'arrive à faire des trucs de base, je ne trouve pas ça plus pratique que du C++/win32, ma Récupérer la description d'une méthode "summary" [ par bmouget ] Bonjour,Aprés chargement d'une Assembly, je voudrais récupérer la description d'une fonction, celle que l'on saisi dans /// .Voici mon code :         classe et assembly [ par chris81 ] bonjour je viens de me mettre au c# et j'y comprend pas gd chose :)j'aimerais savoir comment on fait pour appeler une classe et comment on fait pour c


Nos sponsors


Sondage...

Comparez les prix

CalendriCode

Février 2010
LMMJVSD
1234567
891011121314
15161718192021
22232425262728

Consulter la suite du CalendriCode

 
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,406 sec (3)

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