Search code examples
c#reflection.emitdynamic-type-feature

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";
    }
}

Solution

  • 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.