Reflection.Emit 如何分配不兼容的类型?
How can Reflection.Emit assign incompatible types?
我有两个简单的 classes.
public class A { }
public class B { }
我构建并实例化 class C
如下所示。
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);
问题是我可以成功实例化 class C
。
当我检查 C.A
的类型和值时,我感到非常惊讶。
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
简而言之,我有以下 class 正在工作!
public class A { }
public class B { }
public class C
{
public A A;
public C()
{
this.A = new B();
}
}
我的问题是:
- 这怎么可能?
- CLR 在哪个级别检查类型?
如果您的代码在完全信任的情况下运行,则 CLR 不会费心检查 IL 是否为 "verifiable"。这意味着代码可以做各种疯狂的事情,你有责任确保你发出的代码是类型安全的。
但是,如果您的代码在部分信任下运行,则 Activator.CreateInstance(type)
将抛出 System.Security.VerificationException ("Operation could destabilize the runtime")。
我有两个简单的 classes.
public class A { }
public class B { }
我构建并实例化 class C
如下所示。
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);
问题是我可以成功实例化 class C
。
当我检查 C.A
的类型和值时,我感到非常惊讶。
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
简而言之,我有以下 class 正在工作!
public class A { }
public class B { }
public class C
{
public A A;
public C()
{
this.A = new B();
}
}
我的问题是:
- 这怎么可能?
- CLR 在哪个级别检查类型?
如果您的代码在完全信任的情况下运行,则 CLR 不会费心检查 IL 是否为 "verifiable"。这意味着代码可以做各种疯狂的事情,你有责任确保你发出的代码是类型安全的。
但是,如果您的代码在部分信任下运行,则 Activator.CreateInstance(type)
将抛出 System.Security.VerificationException ("Operation could destabilize the runtime")。