.NET: Impossible de convertir l'objet à l'interface elle met en œuvre
J'ai une classe (TabControlH60) que les deux hérite d'une classe de base (UserControl) et implémente une interface (IFrameworkClient). J'instancie l'objet à l'aide de l' .NET de l'Activateur de la classe. Avec le retour de l'exemple, je lance le UserControl classe de base, mais pas à l'interface. L'exception que je vous est ci-dessous le code snipet. Comment puis-je convertir à l'interface?
object obj = Activator.CreateInstance(objType);
Type[] interfaces = obj.GetType().GetInterfaces(); //contains IFrameworkClient
m_Client = (UserControl)obj; //base class cast works
IFrameworkClient fc = (IFrameworkClient)obj; //interface cast fails
//Note: The (IFrameworkClient)obj cast works fine in the debugger Watch window.
{"Unable to cast object of type 'FPG.H60.AFF.TabControlH60' to type
'FPG.AFF.Interfaces.IFrameworkClient'."}
Vous devez vous connecter pour publier un commentaire.
J'chapeau les mêmes problèmes avec une bibliothèque de mine de fournir un "plugin"de fonctionnalité... je l'ai eu finalement de travail...
Voici mon problème: j'ai eu un assemblage principal à l'aide de plugins, une assemblée avec le plugin (Plugin.dll) ET (important) un autre assemblée fournir le plugin de fonctionnalités (Library.dll).
L'Plugin.dll fait référence à l'assembly principal (afin d'être en mesure de le prolonger) et la Library.dll avec le plugin-func. - c'est binaires ai un répertoire "./Les Plugins" par rapport à l'assemblage principal.
L'assemblage principal également référencé le plugin-func. assemblée afin d'utiliser le "PluginManager" est écrit. Cette "PluginManager" devient un chemin d'accès et les charges de tous *.les fichiers dll via la réflexion afin d'analyser si il y a un "IPlugin"-interface (qui vient de Library.dll trop).
Chaque fois que j'ai appelé le PluginManager pour charger les plugins, il ne pouvait pas les jeter à la "IPlugin" même s'ils sont mis en œuvre.
Je me suis presque fou - mais ensuite, j'ai trouvé l'ensemble du problème. Par la compilation du plugin il n'était pas seulement le "Plugin.dll" mais le "Library.dll" écrit à l' "./Les Plugins" du répertoire. Par mégarde le chargement de l' "Library.dll" à chaque fois avec mon PluginManager j'avais maintenant deux types de "IPlugin" dans le réel "Library.dll" qui est utilisé à partir de l'assemblage principal et celui qui a été chargé par mon PluginManager - et ceux qui étaient incompatibles!
Attention - si vous n'avez pas de charge "./Plugins/Library.dll" toutefois vous rencontrez le problème - parce que si vous chargez "Plugin.dll" références "Library.dll" ensuite, il utilise juste le dans le même répertoire... TILT...!! Mon PluginManager maintenant supprime tout "Library.dll" là où il le trouver.
L'indice est: assurez-vous que vous n'avez pas accès à deux assemblées dans des contextes différents!
La cause la plus probable est ici que
IFrameworkClient
est à partir d'un assemblage différent dans les deux cas, ce qui est différent .Type de NET. Même si c'est le même code, il peut être d'un type différent.Vérifier la
AssemblyQualifiedName
. Notez également que si vous êtes du chargement de cette assemblée, de réflexion, vous pouvez obtenir un autre type de même avec la même AssemblyQualifiedName, grâce à la charge de contexte.Définir IFrameworkClient Interface dans indépendant de l'espace de noms (doit avoir de l'espace de noms) de projet indépendant (bibliothèque de classe).Puis ajouter la refrence de la bibliothèque de classes pour le Contrôle du projet et de projet principal
Quelque chose me dit votre exemple de code est de laisser certaines choses...
Cette compile et s'exécute.
Je parie que la DLL contenant la définition de IFrameworkClient n'a pas encore été chargée avant de vous essayez de lancer. Cela peut se produire lorsque vous êtes à l'aide de l'Activateur.CreateInstance.
Essayez de l'insérer
var forceLoad = typeof(IFrameworkClient);
avant la fonte.Lorsque le
Interface
est dans une autre assemblée et je reçois ma classe dynamiquement àrun-time
dans une autre assemblée,interface casting
l'échec comme votre échantillon (C# connaît notre interface comme un type différent que celui de la classe héritée de qui).C'est ma technique simple et utile dans ce cas:
Quand je suis sûr que mon
Class
a hérité de la mentionnéeInterface
(eq.IFrameworkClient
), donc j'écris une magie ligne de code comme ceci:Par cette technique, vous pouvez:
fc
àdesign time
base surInterface members
info et vs éditeur intelligences système.run-time
Notes:
C# v4
à utiliserdynamic
typedynamic
types dans mes codes, mais il peut nous aider dans certains cas, comme ceSi la classe la glycémie à JEUN.H60.AFF.TabControlH60 en fait de mettre en œuvre IFrameworkClient il devrait y avoir aucune raison ce serait un échec. La seule chose que je peux penser que les causes de cette exception est que si l'assembly qui contient IFrameworkClient est nommé fortement et le Contrôle Onglet objet arrive à faire référence à une version différente de l'contenant de l'assemblée ou vous utilisez une interface différente avec le nom IFrameworkClient.
Dans mon cas, j'ai dû ajouter un événement de construction pour copier les DLL nécessaires depuis que j'ai été la création d'instances et de l'assignation de types d'interface au moment de l'exécution. Sinon, la DLL chargée peut-être pas les plus up-to-date de la DLL, et, par conséquent, peuvent ne pas jeter à l'interface.
La raison, j'ai utilisé des événements de génération dans ce cas (au lieu d'ajouter la DLL en tant que référence), c'est que l'architecture est telle que l'application principale doit uniquement faire référence à des types d'interface, et tout le reste doit être chargés dynamiquement.
TLDR;
Dans le cas de chargement de types dynamiquement à partir d'une autre DLL, assurez-vous de copier la version la plus récente de cette DLL dans le répertoire bin de l'utilisation de créer des événements, autrement casting peut ne pas fonctionner lorsqu'il apparaît qu'il le devrait.
J'ai rencontré le même problème et je viens d'ajouter le code suivant
Bien que, dans la production, il ne sera jamais un problème, dans l'unité de test il était mais maintenant, je n'ai pas besoin de le charger de nouveau et de créer un "autre type"
Le casting n'est pas de travail parce que vous êtes en train de jeter de type
object
à l'interface. Si vous remplacez l'interface cast ligne avec:IFrameworkClient fc = (IFrameworkClient)m_Client;
Il va travailler.
En alternance, je suis légèrement certain que vous pourriez faire de la distribution de l'objet à l'interface avec le
as
opérateur.Voir cet article pour plus d'informations:
http://blogs.msdn.com/ericlippert/archive/2009/10/08/what-s-the-difference-between-as-and-cast-operators.aspx
Encore une pièce du puzzle. Les Interfaces ne dérivent pas de
object
:http://blogs.msdn.com/ericlippert/archive/2009/08/06/not-everything-derives-from-object.aspx
m_Client
etobj
sont presque certainement le même objet (sauf si une conversion est définie). Je ne m'attends pas à ce sujet...