views:

66

answers:

2

I have created a type like this:

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

Then lots of ilgenerating code follows for constructors, methods etc. When I start using the class I noticed something strange. I want to check whether the type 'myname' that i created really implements the ImyInterface. I would expect that both of the following statements 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??
}

So I have created a class that implements ImyInterface but which is not assignable to an object of type ImyInterface, what am I missing?

By the way, there are no generics involved and the Interface is just a basic one to test the concept:

public interface ITestInterface
{
    int CalcSquaredInteger(int number);
}
+1  A: 
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);
        } 
    }
}

this works, so i guess problem is somewhere in code you didn't post here

edit: updated so the IMyInterface is now in another project, and still works

Kikaimaru
"this works, so i guess problem is somewhere in code you didn't post here", well that conclusion is of course right. The strange thing is, my code is similar to your sample. The only difference is that the interface type (IMyInterface in your example) in my case is a parameter of the method that does the whole assembly / type creation. And this type is defined in another namespace / project, so I am digging there to see if that makes a difference. When I cut and paste the interface and hardcode it in the current namespace then it works, but thats not what I need...
Yodah
+1  A: 

I finally found out what I was missing: Whenever you are checking for type compatibility and assignability between types and interfaces that you have defined in different projects/ assemblies, then make sure that all your projects are signed and strongly named!! Otherwise the GetInterface method will work, because that just compares a name. But .net will not assign between types.

Yodah
My guess is, strongly named is enough, signing shouldn't matter in your scenario. Btw: I noticed that the implementation of IsAssignableFrom is quite different in .NET 3.5 and 4.0. What version were you using?
Abel
You are right, strongly named is enough! I'm using 3.5, thanks for pointing that out. I will put on my todo list to check on the behaviour in the 4.0 version
Yodah