.NET 4.0:一段动态绑定代码的底层初级分析

  随着本月12号VS2010的正式发布,相信越来越多的人都会把开发工具升级到VS2010。同时,相信很多人都会用到C# 4.0提供的新功能-动态绑定。我们知道,动态绑定在.NET Framework 4.0里通过一个叫做DLR的来执行的。那么它是怎样实现的呢?请看下面一段代码:

  public  dynamic Foo(dynamic x, dynamic y)
 { 
      
return  x  /  y;
 }

  这个方法代表可以处理所有数值类型的dynamic版本。首先,我们把这个方法编译,然后通过Reflector(版本号:6.1.0.11)查看这个方法的反编译结果,我们会看到如下这样的一个方法:

ExpandedBlockStart.gif 代码
 [ return : Dynamic]
 
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的原型如下:

[CompilerGenerated]
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方法,代码如下:

public   static  CallSite < T >  Create(CallSiteBinder binder)
{
    
return   new  CallSite < T > (binder);
}

然后,我们找到CallSite<T>类的对应构造方法的源代码:

private  CallSite(CallSiteBinder binder) :  base (binder)
{
    
this .Target  =   this .GetUpdateDelegate();
}

然后,我们找到GetUpdateDelegate方法的源代码

private  T GetUpdateDelegate()
{
    
return   this .GetUpdateDelegate( ref  CallSite < T > ._CachedUpdate);
}

再找到GetUpdateDelegate方法的另一个重载版本,如下:

private  T GetUpdateDelegate( ref  T addr)
{
    
if  (((T) addr)  ==   null )
    {
        addr 
=   this .MakeUpdateDelegate();
    }
    
return  addr;
}

于是,我们再找到MakeUpdateDelegate方法,代码如下:

ExpandedBlockStart.gif 代码
internal  T 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的帮助下,我们初步理解了动态绑定的执行过程,对于程序员来讲,这非常重要。

 

 

 

 

转载于:https://www.cnblogs.com/myshell/archive/2010/04/25/1719946.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值