随着本月12号VS2010的正式发布,相信越来越多的人都会把开发工具升级到VS2010。同时,相信很多人都会用到C# 4.0提供的新功能-动态绑定。我们知道,动态绑定在.NET Framework 4.0里通过一个叫做DLR的来执行的。那么它是怎样实现的呢?请看下面一段代码:
{
return x / y;
}
这个方法代表可以处理所有数值类型的dynamic版本。首先,我们把这个方法编译,然后通过Reflector(版本号:6.1.0.11)查看这个方法的反编译结果,我们会看到如下这样的一个方法:
private static object Foo([Dynamic] object x, [Dynamic] object y)
{
if ( < Foo > o__SiteContainer2. <> p__Site3 == null )
{
< Foo > o__SiteContainer2. <> p__Site3 = CallSite < Func < CallSite,
object , object , object >> .Create(Binder.BinaryOperation(
CSharpBinderFlags.None, ExpressionType.Divide,
typeof (Program), new CSharpArgumentInfo[]
{
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null ),
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null )
}));
}
return < Foo > o__SiteContainer2. <> p__Site3.Target(
< Foo > o__SiteContainer2. <> p__Site3, x, y);
}
其中,Program是当前Foo方法所在类的类名。我们会发现,<Foo>o__SiteContainer2这段特殊的代码,通过Reflector的帮助,我们会看到<Foo>o__SiteContainer2的原型如下:
private static class < Foo > o__SiteContainer2
{
public static CallSite < Func < CallSite, object , object , object >> <> p__Site3;
}
原来,编译器生成了一个静态类。再往后看,我们会发现另一个特殊的类:CallSite<T>。在Reflector的帮助下,我们顺利的在System.Runtime.CompilerServices命名空间下找到了它, 我们会看到CallSite<T>类继承自CallSite类。然后,我们找到CallSite<T>类的静态Create方法,代码如下:
{
return new CallSite < T > (binder);
}
然后,我们找到CallSite<T>类的对应构造方法的源代码:
{
this .Target = this .GetUpdateDelegate();
}
然后,我们找到GetUpdateDelegate方法的源代码
{
return this .GetUpdateDelegate( ref CallSite < T > ._CachedUpdate);
}
再找到GetUpdateDelegate方法的另一个重载版本,如下:
{
if (((T) addr) == null )
{
addr = this .MakeUpdateDelegate();
}
return addr;
}
于是,我们再找到MakeUpdateDelegate方法,代码如下:
{
Type[] typeArray;
Type delegateType = typeof (T);
MethodInfo method = delegateType.GetMethod( " Invoke " );
if (delegateType.IsGenericType && CallSite < T > .IsSimpleSignature(method, out typeArray))
{
MethodInfo info2 = null ;
MethodInfo info3 = null ;
if (method.ReturnType == typeof ( void ))
{
if (delegateType == DelegateHelpers.GetActionType(typeArray.AddFirst < Type > ( typeof (CallSite))))
{
info2 = typeof (UpdateDelegates).GetMethod( " UpdateAndExecuteVoid " + typeArray.Length, BindingFlags.NonPublic | BindingFlags.Static);
info3 = typeof (UpdateDelegates).GetMethod( " NoMatchVoid " + typeArray.Length, BindingFlags.NonPublic | BindingFlags.Static);
}
}
else if (delegateType == DelegateHelpers.GetFuncType(typeArray.AddFirst < Type > ( typeof (CallSite))))
{
info2 = typeof (UpdateDelegates).GetMethod( " UpdateAndExecute " + (typeArray.Length - 1 ), BindingFlags.NonPublic | BindingFlags.Static);
info3 = typeof (UpdateDelegates).GetMethod( " NoMatch " + (typeArray.Length - 1 ), BindingFlags.NonPublic | BindingFlags.Static);
}
if (info2 != null )
{
CallSite < T > ._CachedNoMatch = (T) info3.MakeGenericMethod(typeArray).CreateDelegate(delegateType);
return (T) info2.MakeGenericMethod(typeArray).CreateDelegate(delegateType);
}
}
CallSite < T > ._CachedNoMatch = this .CreateCustomNoMatchDelegate(method);
return this .CreateCustomUpdateDelegate(method);
}
一切都明白了。原来,.NET通过一个中间静态类来保存CallSite<T>,只有在第一次执行时,才执行以上这些消耗性能的步骤,第二次执行时,速度会快得多。
最后,在Reflector的帮助下,我们初步理解了动态绑定的执行过程,对于程序员来讲,这非常重要。