2010-07-27 15 views
5

he creado un tipo como éste:¿Por qué IsAssignableFrom y GetInterface dan resultados diferentes

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

Entonces un montón de ilgenerating código siguiente para los constructores, métodos etc. Cuando comienzo a usar la clase me di cuenta de algo extraño. Quiero comprobar si el tipo 'myname' que creé realmente implementa ImyInterface. Yo esperaría que ambas de las siguientes afirmaciones devuelven 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?? 
} 

Así que he creado una clase que implementa IMyInterface pero que no se puede asignar a un objeto de tipo IMyInterface, lo que me estoy perdiendo?

Por cierto, no hay genéricos involucrados y la interfaz es simplemente una básica para poner a prueba el concepto:

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

¿hay genéricos involucrados? ¿cómo se declara la interfaz? –

+0

Sin genéricos, agregué la interfaz de ejemplo a la pregunta. – Yodah

+0

¿Qué es "ImyInterface" en el código anterior? Teniendo en cuenta que estás llamando a un "nombre" de propiedad, no puede ser solo una interfaz, ¿o sí? –

Respuesta

2

finalmente descubrí lo que me faltaba: Siempre que esté mirando para el tipo com patibilidad y asignabilidad entre los tipos e interfaces que ha definido en diferentes proyectos/ensamblajes, luego asegúrese de que todos sus proyectos estén firmados y fuertemente nombrados. De lo contrario, el método GetInterface funcionará, porque eso solo compara un nombre. Pero .net no asignará entre tipos.

+0

Supongo que, dado el nombre es suficiente, la firma no debería importar en su escenario. Por cierto: noté que la implementación de IsAssignableFrom es bastante diferente en .NET 3.5 y 4.0. ¿Qué versión estabas usando? – Abel

+0

¡Tienes razón, el nombre fuerte es suficiente! Estoy usando 3.5, gracias por señalarlo. Voy a poner mi lista de tareas pendientes para verificar el comportamiento en la versión 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); 
     } 
    } 
} 

esto funciona, así que supongo problema está en algún lugar en el código no lo hiciste t post aquí

edición: actualiza por lo que el IMyInterface está ahora en otro proyecto, y todavía funciona

+0

"esto funciona, así que supongo que el problema está en algún lugar del código que no has publicado aquí", bueno, esa conclusión es, por supuesto, correcta. Lo extraño es que mi código es similar a tu muestra. La única diferencia es que el tipo de interfaz (IMyInterface en su ejemplo) en mi caso es un parámetro del método que hace toda la creación del conjunto/tipo. Y este tipo se define en otro espacio de nombres/proyecto, así que estoy excavando allí para ver si eso hace la diferencia. Cuando corté y pegué la interfaz y lo codifiqué en el espacio de nombres actual, funciona, pero eso no es lo que necesito ... – Yodah

Cuestiones relacionadas