2010-07-27 2 views
5

J'ai créé un type comme celui-ci:Pourquoi IsAssignableFrom et GetInterface donnent des résultats différents

TypeBuilder tb = moduleBuilder.DefineType(myname, TypeAttributes.Class | 
     TypeAttributes.Public, typeof(BaseClass), new Type[] { typeof(ImyInterface) }); 

Ensuite, beaucoup de code ilgenerating suit pour les constructeurs, méthodes, etc. Quand je commence à utiliser la classe j'ai remarqué quelque chose d'étrange. Je veux vérifier si le type 'myname' que j'ai créé implémente réellement l'ImyInterface. J'attendre à ce que les deux déclarations suivantes return true:

// t is Type 'myName' 
Type baseInterface = t.GetInterface(typeof(ImyInterface).name); 
if (baseType != null) 
{ 
    // this is actually true, as I expected 
} 

if (typeof(ImyInterface).isAssignableFrom(t)) 
{ 
    // the if clause is false, but I don't have a clue why?? 
} 

J'ai donc créé une classe qui implémente IMyInterface mais qui est incessible à un objet de type IMyInterface, qu'est-ce que je manque?

Par ailleurs, il n'y a pas de génériques en cause et l'interface est juste un de base pour tester le concept:

public interface ITestInterface 
{ 
    int CalcSquaredInteger(int number); 
} 
+0

y a-t-il des génériques impliqués? comment l'interface est-elle déclarée? –

+0

Pas de génériques, j'ai ajouté l'exemple d'interface à la question. – Yodah

+0

Qu'est-ce que "ImyInterface" dans le code ci-dessus? Considérant que vous appelez un "nom" de la propriété, cela ne peut pas être juste une interface, n'est-ce pas? –

Répondre

2

j'ai finalement trouvé ce que je manquais:: Chaque fois que vous vérifiez pour le type com t post ici

modifier patience et assignabilité entre les types et interfaces que vous avez définis dans différents projets/assemblages, alors assurez-vous que tous vos projets sont signés et fortement nommés !! Sinon, la méthode GetInterface fonctionnera, car cela compare simplement un nom. Mais .net n'assignera pas entre les types.

+0

Ma conjecture est, fortement nommé est suffisant, la signature ne devrait pas importer dans votre scénario. Btw: J'ai remarqué que l'implémentation de IsAssignableFrom est assez différente dans .NET 3.5 et 4.0. Quelle version utilisiez-vous? – Abel

+0

Vous avez raison, fortement nommé est assez! J'utilise 3.5, merci de le signaler. Je vais mettre sur ma liste de choses à faire pour vérifier le comportement dans la version 4.0 – Yodah

1
using ClassLibrary1; // this is another project that contains IMyInterface 

namespace ConsoleApplication1 
{ 
    public class MyBaseClass 
    { 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      MyReflectionTest(typeof(ClassLibrary1.IMyInterface)); 
     } 

     private static void MyReflectionTest(Type interfaceType) 
     { 

      AssemblyName aName = new AssemblyName("DynamicAssemblyExample"); 
      AssemblyBuilder ab = AppDomain.CurrentDomain.DefineDynamicAssembly(aName, AssemblyBuilderAccess.RunAndSave); 

      ModuleBuilder mb = ab.DefineDynamicModule(aName.Name, aName.Name + ".dll"); 

      TypeBuilder tb = mb.DefineType("MyDynamicType", TypeAttributes.Public, typeof(MyBaseClass), new Type[] { interfaceType }); 

      MethodBuilder mbIM = tb.DefineMethod("IMyInterface.MyTestMethod", MethodAttributes.Private | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.Final, null, Type.EmptyTypes); 
      ILGenerator il = mbIM.GetILGenerator(); 
      il.Emit(OpCodes.Ret); 

      tb.DefineMethodOverride(mbIM, interfaceType.GetMethod("MyTestMethod")); 

      var myType = tb.CreateType(); 

      Debug.Assert(interfaceType.IsAssignableFrom(myType) == true); 
     } 
    } 
} 

cela fonctionne, donc je suppose problème est quelque part dans le code que vous n » mis à jour de sorte que le IMyInterface est maintenant dans un autre projet, et travaille encore

+0

"cela fonctionne, donc je suppose que le problème est quelque part dans le code que vous n'avez pas posté ici", bien cette conclusion est bien sûr juste. La chose étrange est, mon code est similaire à votre échantillon. La seule différence est que le type d'interface (IMyInterface dans votre exemple) dans mon cas est un paramètre de la méthode qui fait l'ensemble de la création de l'assemblage/type. Et ce type est défini dans un autre espace de noms/projet, donc je creuse là pour voir si cela fait une différence. Quand je coupe et colle l'interface et le code en dur dans l'espace de nom actuel, alors ça marche, mais ce n'est pas ce dont j'ai besoin ... – Yodah