惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Google Online Security Blog
Google Online Security Blog
C
CXSECURITY Database RSS Feed - CXSecurity.com
C
CERT Recently Published Vulnerability Notes
C
Cybersecurity and Infrastructure Security Agency CISA
Cisco Talos Blog
Cisco Talos Blog
Hacker News - Newest:
Hacker News - Newest: "LLM"
Scott Helme
Scott Helme
Project Zero
Project Zero
E
Exploit-DB.com RSS Feed
S
Secure Thoughts
K
Kaspersky official blog
L
Lohrmann on Cybersecurity
NISL@THU
NISL@THU
WordPress大学
WordPress大学
N
News and Events Feed by Topic
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
L
LINUX DO - 热门话题
小众软件
小众软件
P
Privacy & Cybersecurity Law Blog
博客园 - 聂微东
Google DeepMind News
Google DeepMind News
H
Hackread – Cybersecurity News, Data Breaches, AI and More
A
About on SuperTechFans
Hacker News: Ask HN
Hacker News: Ask HN
AWS News Blog
AWS News Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
H
Hacker News: Front Page
F
Full Disclosure
Latest news
Latest news
Schneier on Security
Schneier on Security
The Hacker News
The Hacker News
T
Troy Hunt's Blog
www.infosecurity-magazine.com
www.infosecurity-magazine.com
Jina AI
Jina AI
Martin Fowler
Martin Fowler
P
Proofpoint News Feed
TaoSecurity Blog
TaoSecurity Blog
G
GRAHAM CLULEY
Forbes - Security
Forbes - Security
V
V2EX - 技术
酷 壳 – CoolShell
酷 壳 – CoolShell
V
Vulnerabilities – Threatpost
C
Cyber Attacks, Cyber Crime and Cyber Security
MongoDB | Blog
MongoDB | Blog
博客园 - 三生石上(FineUI控件)
S
SegmentFault 最新的问题
Hugging Face - Blog
Hugging Face - Blog
P
Privacy International News Feed
C
Check Point Blog
N
News and Events Feed by Topic

博客园 - 残香恨

WinForm:如何设置DataGridView列标题对齐方式 WinForm:如何在ListBox中添加CheckBox ASP.NET WebForm开发WAP网站 lock语句的递归问题 VS 2010 调试 .NET Framework 源代码 最近遇到的两个问题 ASP.NET MVC 2 模板化辅助方法 SynchronizationContext对Windows Forms窗体控件的更新方法 - 残香恨 SQL Server 2008 Express 升级R2全过程 自定义ASP.NET MVC Html辅助方法 - 残香恨 将ASP.NET MVC 1.0升级到ASP.NET MVC 2的三种方法 Visual Studio 2010 RTM版安装初体验 .NET中的线程 .NET 4.0 任务(Task) C#4.0 动态绑定(Dynamic Binding) .NET4.0新功能:任务(Task) .NET4.0线程池的Cooperative Cancellation模式 Visual Studio 2010 RC初体验 SQL Server导入文本文件时选择相同数据类型的一个小技巧
.NET 4.0:一段动态绑定代码的底层初级分析
残香恨 · 2010-04-25 · via 博客园 - 残香恨

  随着本月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)查看这个方法的反编译结果,我们会看到如下这样的一个方法:

代码

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

代码

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