How does Reflection.Emit assign incompatible types?

I have two simple classes.

public class A { } public class B { } 

I create and create an instance of class C as shown below.

 var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("Some.Namespace"), AssemblyBuilderAccess.Run); var moduleBuilder = assemblyBuilder.DefineDynamicModule(assemblyBuilder.GetName().Name); // public class C var typeBuilder = moduleBuilder.DefineType("C", TypeAttributes.Public | TypeAttributes.Class, typeof(object)); // public AA; var aField = typeBuilder.DefineField("A", typeof(A), FieldAttributes.Public); // public C() { this.A = new B(); } !!!! var ctorBuilder = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, Type.EmptyTypes); var ctorIL = ctorBuilder.GetILGenerator(); ctorIL.Emit(OpCodes.Ldarg_0); ctorIL.Emit(OpCodes.Newobj, typeof(B).GetConstructor(Type.EmptyTypes)); ctorIL.Emit(OpCodes.Stfld, aField); ctorIL.Emit(OpCodes.Ret); // return new C(); var type = typeBuilder.CreateType(); return Activator.CreateInstance(type); 

The problem is that I can successfully create the C class. When I check the type and value of CA , it was very surprising for me.

 var c = CreateC(); var field = c.GetType().GetField("A"); var fieldValue = c.GetType().GetField("A").GetValue(c); Console.WriteLine(typeof(A) == field.FieldType); // True Console.WriteLine(typeof(A) == fieldValue.GetType()); // False Console.WriteLine(typeof(B) == field.FieldType); // False Console.WriteLine(typeof(B) == fieldValue.GetType()); // True 

In short, I have the following classes that work!

 public class A { } public class B { } public class C { public AA; public C() { this.A = new B(); } } 

My questions:

  • How is this possible?
  • At what level does the CLR check types?
+5
source share
1 answer

If your code works under full trust, the CLR does not bother to verify that the IL is โ€œverifiableโ€. This means that the code can do all kinds of crazy things, and it is your responsibility to make sure that the code you emit is type safe.

However, if your code runs under private trust, then Activator.CreateInstance(type) will throw a System.Security.VerificationException ("Operation may destabilize runtime").

+3
source

All Articles