动态变量转化为动态类型
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。我真的,真的不认为你想那样做。
是否可以生成动态类型并在方法中使用反射发出动态变量?动态类型类似于下面的代码,但使用反射发射创建。
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。我真的,真的不认为你想那样做。