Comment bien mouler des objets créés par réflexion
Je suis d'essayer d'envelopper ma tête autour de la réflexion, j'ai donc décidé d'ajouter un plugin capacité d'un programme que je suis en train d'écrire. La seule façon de comprendre un concept est d'obtenir vos doigts sales et écrire le code, je suis donc allé à la route de la création d'une interface simple bibliothèque composée de la IPlugin et IHost interfaces, un plugin de mise en œuvre de la bibliothèque de classes qui implémentent IPlugin, et une simple console de projet qui instancie le IHost mise en œuvre de la classe qui n'simple de travailler avec le plugin objets.
L'aide de la réflexion, j'ai voulu faire une itération sur les types de contenus à l'intérieur de mon plugin de mise en œuvre de la dll et de créer des instances de types. J'ai été en mesure de réussi à instancier des classes avec ce code, mais je ne pouvais pas jeté l'objet créé à l'interface.
J'ai essayé ce code mais je ne pouvais pas le cast de l'objet o comme je m'y attendais. J'ai marché à travers le processus avec le débogueur et le bon constructeur est appelé. Quickwatching objet o m'a montré qu'il avait les champs et les propriétés que je m'attendais à voir dans la mise en œuvre de la classe.
loop through assemblies
loop through types in assembly
//Filter out unwanted types
if (!type.IsClass || type.IsNotPublic || type.IsAbstract )
continue;
//This successfully created the right object
object o = Activator.CreateInstance(type);
//This threw an Invalid Cast Exception or returned null for an "as" cast
//even though the object implemented IPlugin
IPlugin i = (IPlugin) o;
J'ai fait le code du travail.
using System.Runtime.Remoting;
ObjectHandle oh = Activator.CreateInstance(assembly.FullName, type.FullName);
//This worked as I intended
IPlugin i = (IPlugin) oh.Unwrap();
i.DoStuff();
Voici mes questions:
- Activateur.CreateInstance(Type t) retourne un objet, mais je n'arrivais pas à convertir l'objet à une interface de l'objet mis en œuvre. Pourquoi?
- Si j'ai été en utilisant un autre surcharge de la méthode CreateInstance()?
- Ce sont la réflexion en matière de conseils et d'astuces?
- Est-il un élément crucial de la réflexion que je suis tout simplement pas l'obtenir?
source d'informationauteur Ben Robbins
Vous devez vous connecter pour publier un commentaire.
Je suis juste deviner ici, car à partir de votre code, il n'est pas évident de l'endroit où vous avez définition de IPlugin interface, mais si vous ne pouvez pas jeter dans votre application hôte, alors vous êtes probablement avoir IPlugin interface de l'hôte de l'assemblée et puis en même temps dans votre plugin assemblée. Cela ne fonctionnera pas.
La chose la plus facile est de faire de ce travail est d'avoir IPlugin interface marqué comme public dans votre hôte de l'assemblée et ensuite votre Plugin assemblée de référence de l'application hôte de l'assembléede sorte que les deux assemblées ont accès à la même interface.
hmmm... Si vous utilisez de l'Assemblée.LoadFrom pour charger votre assemblée essayez de la remplacer par l'Assemblée.LoadFile à la place.
A fonctionné pour moi
À partir d'ici: http://www.eggheadcafe.com/community/aspnet/2/10036776/solution-found.aspx
@lubos hasko
Vous a cloué sur le nez. Ma conception originale n'ont les trois montages différents, avec à la fois l'hôte et le plugin de mise en œuvre de référencement de l'interface du plugin assembly.
J'ai essayé une solution distincte avec un hôte de mise en œuvre et de l'interface de l'assemblée et un plugin de mise en œuvre de l'assemblée. Dans cette solution, le code dans le premier bloc a fonctionné comme prévu.
Que vous m'avez donnée un peu plus à le penser, car je ne suis pas tout à fait comprendre pourquoi les deux assemblées de la référence d'une assemblée commune n'est pas d'obtenir le même type de l'assemblée commune.
J'essayais juste de faire ce travail moi-même et réussi à tomber sur la réponse!
J'ai eu 3 différents projets C#
J'ai été faire l'erreur de casting ainsi jusqu'à ce que j'ai changé le nom de l'assembly pour mon Plugin Interface proj pour correspondre à l'espace de noms de ce que j'étais en train de jeter à.
E. g.
a échoué car l'assemblée que le IPluginModule interface a été définie en a été appelée "Commune", Le type I a été coulée à a 'Bla.Les Plugins.Commun.IPluginModule " toutefois.
J'ai changé le nom de l'Assemblage de l'interface proj être " Blah.Les Plugins.Commun", cela signifiait que le casting réussi.
J'espère que cette explication aide à quelqu'un. De retour pour le code..
Est votre type n'est pas public, si oui, appelez la surcharge qui prend dans un booléen:
Aussi, dans votre premier exemple, si o est nulle et si pas le, imprimez-o.GetType().Nom pour voir ce qu'il est vraiment.
@Haacked
J'ai essayé de garder le pseudo-code simple. foreach prendre beaucoup d'espace et de croisillons. J'ai clarifié.
o.GetType().FullName retourne Plugins.Multipliez ce qui est l'objet attendu. Les Plugins.Multiplier implémente IPlugin. Je passais à travers le processus dans le débogueur tout à fait à quelques reprises jusqu'à ce que j'ai donné pour la soirée. Ne pouvais pas comprendre pourquoi je ne pouvais pas le jeter parce que j'ai regardé le constructeur feu jusqu'à ce que je suis grincheux de tout ce gâchis. Est revenu ce soir et de le faire fonctionner, mais je ne comprends toujours pas pourquoi le casting a échoué dans le premier bloc de code. Le deuxième bloc de code fonctionne, mais il se sent hors de moi.
Le lien à tête d'oeuf ci-dessus est la principale solution au problème de l'utilisation de l'Assemblée.LoadFile() au lieu de .LoadFrom()