2010-07-27 14 views
5

ho creato un tipo come questo:Perché IsAssignableFrom e GetInterface dare risultati diversi

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

poi un sacco di ilgenerating codice seguente per i costruttori, metodi ecc Quando inizio a utilizzare la classe ho notato qualcosa di strano. Voglio verificare se il tipo "myname" che ho creato implementa davvero ImyInterface. Mi aspetterei che entrambe le seguenti istruzioni 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?? 
} 

Così ho creato una classe che implementa IMyInterface ma che non è assegnabile a un oggetto di tipo IMyInterface, cosa mi manca?

A proposito, non ci sono generici coinvolti e l'interfaccia è solo uno di base per testare il concetto:

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

ci sono generici coinvolti? come viene dichiarata l'interfaccia? –

+0

No generici, ho aggiunto l'interfaccia di esempio alla domanda. – Yodah

+0

Che cos'è "ImyInterface" nel codice sopra? Considerando che stai chiamando un "nome" di proprietà su di esso non può essere solo un'interfaccia può? –

risposta

2

ho finalmente scoperto quello che mi mancava: Ogni volta che si sta verificando per il tipo com la brevettabilità e l'assegnabilità tra tipi e interfacce che hai definito in diversi progetti/assiemi, quindi assicurati che tutti i tuoi progetti siano firmati e fortemente nominati !! Altrimenti funzionerà il metodo GetInterface, perché confronta solo un nome. Ma. Net non assegnerà tra i tipi.

+0

La mia ipotesi è, il nome è abbastanza forte, la firma non dovrebbe importare nel tuo scenario. A proposito: ho notato che l'implementazione di IsAssignableFrom è abbastanza diversa in .NET 3.5 e 4.0. Che versione stavi usando? – Abel

+0

Hai ragione, il nome forte è sufficiente! Sto usando 3.5, grazie per averlo indicato. Inserirò la mia lista di cose da fare per verificare il comportamento nella versione 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); 
     } 
    } 
} 

questo funziona, quindi credo che problema è da qualche parte nel codice che didn' t post qui

edit: aggiornamento in modo che l'IMyInterface è ora in un altro progetto, e funziona ancora

+0

"questo funziona, quindi credo che il problema sia da qualche parte nel codice che non hai postato qui", beh, quella conclusione è ovviamente giusta. La cosa strana è che il mio codice è simile al tuo campione. L'unica differenza è che il tipo di interfaccia (IMyInterface nel tuo esempio) nel mio caso è un parametro del metodo che esegue l'intera assemblaggio/tipo di creazione. E questo tipo è definito in un altro namespace/progetto, quindi sto scavando lì per vedere se questo fa la differenza. Quando faccio a tagliare e incollare l'interfaccia e lo hardcode nello spazio dei nomi corrente funziona, ma non è quello che mi serve ... – Yodah

Problemi correlati