简体   繁体   English

Reflection.Emit如何分配不兼容的类型?

[英]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. 我构建并实例化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);

The problem is I can successfully instantiate class C . 问题是我可以成功实例化C类。 When I check the type and value of CA it was very surprising for me. 当我检查CA的类型和价值时,对我来说这是非常令人惊讶的。

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? CLR在哪个级别检查类型?

If your code runs under full trust, then the CLR doesn't bother checking that the IL is "verifiable". 如果您的代码在完全信任下运行,则CLR不会检查IL是否“可验证”。 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"). 但是,如果您的代码在部分信任下运行,那么Activator.CreateInstance(type)将抛出System.Security.VerificationException (“Operation可能会破坏运行时的稳定性”)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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