Main方法如下:
Console.WriteLine();
Console.WriteLine(str.Substring(1));
Console.ReadLine();
}
使用reflactor 反编译下,可以看到:
完整代码如下:
Console.WriteLine(str.Length);
Console.WriteLine();
Console.WriteLine(str.Substring(1));
一共使用了四次dynamic对象。1:Console.WriteLine(dynamic); str.Length返回dynamic2:dynamic.Length;3:Console.WriteLine(dynamic); str.Substring 返回dynamic4:dynamic.Substring(1); 1,2,3,4,分别对应上面的<>p_Site1,2,3,4;
因为1,3 都是无返回值的,所以是Action, 2,4都有返回值,所以是Func. 看上面的代码可能还不清楚,让我们手动的生成下代码吧:新建类SiteContainer 来取代编译器自动生成的类。
SiteContainer.p__Site2 = CallSite
}
可以看到,和p__Site1不同的是,调用的是GetMember方法。
既然有了两个CallSite的对象,那么它们又是如何调用的呢??
使用CallSite.Target 就可以调用了。
//这是编译器生成的代码://SiteContainer.p__Site1.Target(SiteContainer.p__Site1, typeof(Console), // SiteContainer.p__Site2.Target(SiteContainer.p__Site2, obj1) //); var pSite2Result = SiteContainer.p__Site2.Target(SiteContainer.p__Site2, obj1); SiteContainer.p__Site1.Target(SiteContainer.p__Site1, typeof(Console), pSite2Result);
看看如何调用的吧:
因为SiteContainer.p__Site2,是调用Length属性
首先调用p__Site2的target方法,执行p__Site2,对象是obj1.
dlr 就会调用obj1.Length,并返回结果,所以pSite2Result=4;
接着调用p__Site1的target,来调用Console类的WriteLine方法,参数是pSite2Result.所以输出4.
最后来看下dynamic是如何调用Substring方法的:
Substring方法对应的是p__Site4,因为Substring方法传递了个参数1,并且有返回值,所以
p__Site4对象是:
public static CallSite
初始化:
if (SiteContainer.p__Site4 == null)
{
CallSiteBinder csb = Microsoft.CSharp.RuntimeBinder.Binder.InvokeMember(
CSharpBinderFlags.None, "Substring", null, typeof(Program),
new CSharpArgumentInfo[]
{
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null),
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.Constant
| CSharpArgumentInfoFlags.UseCompileTimeType, null)
});
SiteContainer.p__Site4 = CallSite
}
基本和上面的p__Site1类似,只是参数信息是:CSharpArgumentInfoFlags.Constant \
因为调用了Substring(1).在编译的时候会传递1进去,而1是常量。 调用如下:
完整的Main函数代码如下:
if (SiteContainer.p__Site1 == null)
{
CallSiteBinder csb = Microsoft.CSharp.RuntimeBinder.Binder.InvokeMember(
CSharpBinderFlags.ResultDiscarded,
"WriteLine", null, typeof(Program),
new CSharpArgumentInfo[]
{
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.IsStaticType | CSharpArgumentInfoFlags.UseCompileTimeType,null),
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None,null)
});
SiteContainer.p__Site1 = CallSite
}
if (SiteContainer.p__Site2 == null)
{
CallSiteBinder csb = Microsoft.CSharp.RuntimeBinder.Binder.GetMember(
CSharpBinderFlags.None, "Length", typeof(Program),
new CSharpArgumentInfo[]
{
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null)
});
SiteContainer.p__Site2 = CallSite
}
if (SiteContainer.p__Site4 == null)
{
CallSiteBinder csb = Microsoft.CSharp.RuntimeBinder.Binder.InvokeMember(
CSharpBinderFlags.None, "Substring", null, typeof(Program),
new CSharpArgumentInfo[]
{
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null),
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null)
});
SiteContainer.p__Site4 = CallSite
}
var lengthResult = SiteContainer.p__Site2.Target(SiteContainer.p__Site2, obj1);
SiteContainer.p__Site1.Target(SiteContainer.p__Site1, typeof(Console), lengthResult);
var subStringResult = SiteContainer.p__Site4.Target(SiteContainer.p__Site4, obj1, 1);
SiteContainer.p__Site1.Target(SiteContainer.p__Site1, typeof(Console), subStringResult);
Console.ReadLine();
}