cs_Warny
Messages postés473Date d'inscriptionmercredi 7 août 2002StatutMembreDernière intervention10 juin 2015
-
18 févr. 2007 à 22:04
EmacLi
Messages postés165Date d'inscriptionjeudi 3 novembre 2005StatutMembreDernière intervention 1 février 2013
-
20 mai 2009 à 21:57
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 {
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>
///Element servant de clef
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>
///Chemin Contenant les assemblies à charger
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>
///
//Récupère tous les type contenus
Type[] types = assembly.GetTypes();
foreach (
Type type
in types) {AddType(type);
}
}
///<summary>
/// Ajoute un type
///</summary>
///Type à ajouter
private
void 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,
//charge le type particulier
Type type = assembly.GetType(ClassName);
//Ajoute le type
AddType(type);}
///<summary>
/// Retire un type de la liste
///</summary>
///Clef du type à enlever
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>
///Type à tester
///Référence
///<returns></returns>
private
bool IsBasedOn(
Type TestType,
Type BaseType) {
if (TestType.IsSubclassOf(BaseType))
return
true;
if (TestType.FullName == BaseType.FullName)
return
true;
if (TestType.FullName ==
"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>
///Identifiant de l'élément à créer
///Paramètres du constructeur
///<returns>Objet de la classe de base</returns>
public BaseClass Create(
string Id,
params
object[] parameters) {
cs_coq
Messages postés6349Date d'inscriptionsamedi 1 juin 2002StatutMembreDernière intervention 2 août 2014101 18 févr. 2007 à 22:59
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.
cs_Warny
Messages postés473Date d'inscriptionmercredi 7 août 2002StatutMembreDernière intervention10 juin 2015 19 févr. 2007 à 08:10
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