简体   繁体   中英

Dynamic variable into a dynamic type

Is it possible to generate a dynamic type and in a method a dynamic variable using reflection emit? The dynamic type would be something like the code below but created by using reflection emit.

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

You can do this - but it would be incredibly difficult (at least if you want to do anything usefully dynamic - just assigning a value to a local varaible would be easy enough, but I assume your real code would do more than that). Dynamic typing is handled by the C# compiler; there's no IL for it... whereas Reflection.Emit is all about generating IL.

So this piece of code:

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

generates the following IL - as well as a generated class, referred to in the 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

You'd have to write Reflection.Emit code to generate all that IL yourself. I really, really don't think you want to do that.

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