标题基本上是我的问题。在封面下是最后一行:
Type xmlCodecType = typeof(XmlCodec<>).MakeGenericType(typeof(SomeObjectProperty));
dynamic xmlCodec = Activator.CreateInstance(xmlCodecType);
xmlCodec.ReadCollection(xmlCodec.GetCollectionName());
基本上这样做:
MethodInfo method1 = xmlCodec.GetType().GetMethod("ReadCollection");
MethodInfo method2 = xmlCodec.GetType().GetMethod("GetCollectionName");
method1.Invoke(xmlCodec, new obj[] { method2.Invoke(xmlCodec, null) });
执行时??
我写的大部分内容都是使用反射方法,因为它是我习惯的,只是感觉更多'在编译期间捕获错误'传递写类型和对象等。动态是更多的动手。然而,有时候反思可能更难以阅读/跟随,而动态并不总是语言中的关键词,而且大多数都是常见的概念。
答案 0 :(得分:1)
这里有一小段测试代码:
void Main()
{
this.DoSomething();
}
private void DoSomething()
{
Console.WriteLine("Foo");
}
编译成这个IL:
IL_0000: nop
IL_0001: ldarg.0
IL_0002: call UserQuery.DoSomething
IL_0007: nop
IL_0008: ret
DoSomething:
IL_0000: nop
IL_0001: ldstr "Foo"
IL_0006: call System.Console.WriteLine
IL_000B: nop
IL_000C: ret
现在,如果我引入dynamic
引用:
void Main()
{
dynamic bar = this;
bar.DoSomething();
}
private void DoSomething()
{
Console.WriteLine("Foo");
}
这是IL:
IL_0000: nop
IL_0001: ldarg.0
IL_0002: stloc.0 // bar
IL_0003: ldsfld UserQuery+<Main>o__SiteContainer0.<>p__Site1
IL_0008: brtrue.s IL_0042
IL_000A: ldc.i4 00 01 00 00
IL_000F: ldstr "DoSomething"
IL_0014: ldnull
IL_0015: ldtoken UserQuery
IL_001A: call System.Type.GetTypeFromHandle
IL_001F: ldc.i4.1
IL_0020: newarr Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo
IL_0025: stloc.1 // CS$0$0000
IL_0026: ldloc.1 // CS$0$0000
IL_0027: ldc.i4.0
IL_0028: ldc.i4.0
IL_0029: ldnull
IL_002A: call Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo.Create
IL_002F: stelem.ref
IL_0030: ldloc.1 // CS$0$0000
IL_0031: call Microsoft.CSharp.RuntimeBinder.Binder.InvokeMember
IL_0036: call System.Runtime.CompilerServices.CallSite<System.Action<System.Runtime.CompilerServices.CallSite,System.Object>>.Create
IL_003B: stsfld UserQuery+<Main>o__SiteContainer0.<>p__Site1
IL_0040: br.s IL_0042
IL_0042: ldsfld UserQuery+<Main>o__SiteContainer0.<>p__Site1
IL_0047: ldfld System.Runtime.CompilerServices.CallSite<System.Action<System.Runtime.CompilerServices.CallSite,System.Object>>.Target
IL_004C: ldsfld UserQuery+<Main>o__SiteContainer0.<>p__Site1
IL_0051: ldloc.0 // bar
IL_0052: callvirt System.Action<System.Runtime.CompilerServices.CallSite,System.Object>.Invoke
IL_0057: nop
IL_0058: ret
DoSomething:
IL_0000: nop
IL_0001: ldstr "Foo"
IL_0006: call System.Console.WriteLine
IL_000B: nop
IL_000C: ret
这反编译为:
private void Main()
{
object obj = (object)this;
if (SiteContainer.Site == null)
SiteContainer.Site = CallSite<Action<CallSite, object>>.Create(Microsoft.CSharp.RuntimeBinder.Binder.InvokeMember(CSharpBinderFlags.ResultDiscarded, "DoSomething", (IEnumerable<Type>)null, typeof(UserQuery), (IEnumerable<CSharpArgumentInfo>) new CSharpArgumentInfo[1]
{
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, (string) null)
}));
SiteContainer.Site.Target((CallSite)SiteContainer.Site, obj);
}
private void DoSomething()
{
Console.WriteLine("Foo");
}
[CompilerGenerated]
private static class SiteContainer
{
public static CallSite<Action<CallSite, object>> Site;
}
所以,就我所知,究竟是什么叫做。
答案 1 :(得分:0)
不,一个方法不是简单地用这个名字查找的。 (dynamic
不仅限于方法,但它也可以用于绑定到fields / properties。)如果有问题的类扩展DynamicObject
,实际上可以操作绑定表达式。举个简单的例子:
class DynamicDictionary : DynamicObject {
private Dictionary<string, object> Dict = /*...*/;
public override bool TryGetMember(GetMemberBinder binder, out object result) {
result = Dict[binder.Name];
return true;
}
}
现在,如果您运行以下代码:
dynamic dict = new DynamicDictionary();
object o = dict.Abc123;
DynamicDictionary
,不会尝试获取字段或属性dict.Abc123
,而是尝试查找并返回Dict["Abc123"]
。
编辑:发现dynamic
工作here的更深入的帖子。