动态变量转化为动态类型

Dynamic variable into a dynamic type

是否可以生成动态类型并在方法中使用反射发出动态变量?动态类型类似于下面的代码,但使用反射发射创建。

public class MyDynamicType
{
    public void MyTests()
    {
        dynamic MyDynamicVar = 10;
        MyDynamicVar = "whatever";
    }
}

可以做到这一点 - 但它 难以置信 困难(至少如果你想做任何有用的动态 - 只需分配一个局部变量的值就足够简单了,但我假设你的真实代码会做更多的事情)。动态类型由 C# 编译器处理;它没有 IL...而 Reflection.Emit 就是生成 IL。

所以这段代码:

static void Main()
{
    dynamic x = "foo";
    dynamic y = x.Substring(1, 2);
}

生成以下 IL - 以及生成的 class,在 IL 中引用:

.method private hidebysig static void  Main() cil managed
{
  .entrypoint
  // Code size       109 (0x6d)
  .maxstack  9
  .locals init (object V_0,
           object V_1)
  IL_0000:  nop
  IL_0001:  ldstr      "foo"
  IL_0006:  stloc.0
  IL_0007:  ldsfld     class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`5<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32,int32,object>> Program/'<>o__0'::'<>p__0'
  IL_000c:  brfalse.s  IL_0010
  IL_000e:  br.s       IL_0054
  IL_0010:  ldc.i4.0
  IL_0011:  ldstr      "Substring"
  IL_0016:  ldnull
  IL_0017:  ldtoken    Program
  IL_001c:  call       class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
  IL_0021:  ldc.i4.3
  IL_0022:  newarr     [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo
  IL_0027:  dup
  IL_0028:  ldc.i4.0
  IL_0029:  ldc.i4.0
  IL_002a:  ldnull
  IL_002b:  call       class [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo::Create(valuetype [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfoFlags,
                                                                                                                                                                             string)
  IL_0030:  stelem.ref
  IL_0031:  dup
  IL_0032:  ldc.i4.1
  IL_0033:  ldc.i4.3
  IL_0034:  ldnull
  IL_0035:  call       class [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo::Create(valuetype [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfoFlags,
                                                                                                                                                                             string)
  IL_003a:  stelem.ref
  IL_003b:  dup
  IL_003c:  ldc.i4.2
  IL_003d:  ldc.i4.3
  IL_003e:  ldnull
  IL_003f:  call       class [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo::Create(valuetype [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfoFlags,
                                                                                                                                                                             string)
  IL_0044:  stelem.ref
  IL_0045:  call       class [System.Core]System.Runtime.CompilerServices.CallSiteBinder [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.Binder::InvokeMember(valuetype [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags,
                                                                                                                                                               string,
                                                                                                                                                               class [mscorlib]System.Collections.Generic.IEnumerable`1<class [mscorlib]System.Type>,
                                                                                                                                                               class [mscorlib]System.Type,
                                                                                                                                                               class [mscorlib]System.Collections.Generic.IEnumerable`1<class [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo>)
  IL_004a:  call       class [System.Core]System.Runtime.CompilerServices.CallSite`1<!0> class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`5<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32,int32,object>>::Create(class [System.Core]System.Runtime.CompilerServices.CallSiteBinder)
  IL_004f:  stsfld     class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`5<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32,int32,object>> Program/'<>o__0'::'<>p__0'
  IL_0054:  ldsfld     class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`5<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32,int32,object>> Program/'<>o__0'::'<>p__0'
  IL_0059:  ldfld      !0 class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`5<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32,int32,object>>::Target
  IL_005e:  ldsfld     class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`5<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32,int32,object>> Program/'<>o__0'::'<>p__0'
  IL_0063:  ldloc.0
  IL_0064:  ldc.i4.1
  IL_0065:  ldc.i4.2
  IL_0066:  callvirt   instance !4 class [mscorlib]System.Func`5<class [System.Core]System.Runtime.CompilerServices.CallSite,object,int32,int32,object>::Invoke(!0,
                                                                                                                                                                !1,
                                                                                                                                                                !2,
                                                                                                                                                                !3)
  IL_006b:  stloc.1
  IL_006c:  ret
} // end of method Program::Main

您必须自己编写 Reflection.Emit 代码来生成所有 IL。我真的,真的不认为你想那样做。