简体   繁体   中英

How can Reflection.Emit assign incompatible types?

I have two simple classes.

public class A { }
public class B { }

I build and instantiate class C like 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 A A;
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 I can successfully instantiate class C . 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

Briefly, I have following classes which are working!

public class A { }
public class B { }

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

My questions are:

  1. How can this be possible?
  2. At which level does CLR checks the types?

If your code runs under full trust, then the CLR doesn't bother checking that the IL is "verifiable". This means that the code can do all sorts of crazy things, and it's your responsibility to make sure the code you emit is type safe.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM