仓酷云

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 724|回复: 7
打印 上一主题 下一主题

[学习教程] ASP.NET网页编程之探究.Net中的托付

[复制链接]
飘灵儿 该用户已被删除
跳转到指定楼层
楼主
发表于 2015-1-16 22:23:14 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
你觉得学习.NET怎么样,我懂的少,问的可能很幼稚,见笑了啊:)我原本觉得托付很复杂,原本只想简复杂单的说说托付面前的器材,托付的利用办法。底本只想注释一下那句:托付是面向工具的、范例平安的函数指针。可没想到最初惹出一堆的事变来,越惹越多,罪恶,罪恶。本文前面一部分是我在一边用SOS探究一边纪录的,写的十分糟,但愿您的慧眼能发明一些有代价的器材,那我就感应非常的侥幸了。托付宿世与此生
人人大概还记得,在C/C++里,我们能够在一个函数里完成一个算法的骨架,然后在这个函数的参数里放一个“钩子”,利用的时分,使用这个“钩子”注进一个函数,注进的函数完成分歧算法的分歧部分,如许就能够到达算法骨架重用的目标。而这里所谓的“钩子”就是“函数指针”。这个功效很壮大啊,可是函数指针却有它的优势:不是范例平安的、只能“钩”一个函数。人人大概都晓得微软对托付的形貌:托付是一种面向工具的,范例平安的,能够多播的函数指针。要了解这句话,我们先来看看用C#的关头字delegate声明的一个托付究竟是甚么样的器材:
  1. 1:namespaceYuyijq.DotNet.Chapter2
复制代码
  1. 2:{
复制代码
  1. 3:publicdelegatevoidMyDelegate(intpara);
复制代码
  1. 4:}
复制代码
埋没在面前的奥密
很复杂的代码吧,利用ILDasm反编译一下:

奇异的是,这么复杂的一行代码,酿成了一个类:类名与托付名分歧,这个类承继自System.MulticastDelegate类,连机关器一同有四个成员。看看我们怎样利用这个托付:
  1. 1:publicclassTestDelegate
复制代码
  1. 2:{
复制代码
  1. 3:MyDelegatemyDelegate;
复制代码
  1. 4:
复制代码
  1. 5:publicvoidAssignDelegate()
复制代码
  1. 6:{
复制代码
  1. 2:{0
复制代码
  1. 2:{1
复制代码
  1. 2:{2
复制代码
  1. 2:{3
复制代码
  1. 2:{4
复制代码
  1. 2:{5
复制代码
  1. 2:{6
复制代码
  1. 2:{7
复制代码
编译后用ILDasm看看了局:
.fieldprivateclassYuyijq.DotNet.Chapter2.MyDelegatemyDelegate
发明,.Net把托付就当作一个范例,与其他范例一样看待,如今你分明了下面那句话中说托付是面向工具的函数指针的意义了吧。
接着看看AssignDelegate反编译后的代码:
  1. 2:{8
复制代码
  1. 2:{
复制代码
  1. 3:publicdelegatevoidMyDelegate(intpara);0
复制代码
  1. 3:publicdelegatevoidMyDelegate(intpara);1
复制代码
  1. 3:publicdelegatevoidMyDelegate(intpara);2
复制代码
  1. 3:publicdelegatevoidMyDelegate(intpara);3
复制代码
  1. 3:publicdelegatevoidMyDelegate(intpara);4
复制代码
  1. 3:publicdelegatevoidMyDelegate(intpara);5
复制代码
  1. 3:publicdelegatevoidMyDelegate(intpara);6
复制代码
  1. 3:publicdelegatevoidMyDelegate(intpara);7
复制代码
  1. 3:publicdelegatevoidMyDelegate(intpara);8
复制代码
  1. 3:publicdelegatevoidMyDelegate(intpara);9
复制代码
  1. 4:}0
复制代码
  1. 4:}1
复制代码
  1. 4:}2
复制代码
经由过程下面的代码,我们会发明,将一个实例办法分派给托付时,托付不单单援用了办法的地点,另有这个办法地点工具的援用,这里就是所谓的范例平安。
我们再回过火来看看MyDelegate的承继链:MyDelegate->MulticastDelegate->Delegate。
奇奥的中央
而Delegate中有三个风趣的字段:
internalobject_target;
internalIntPtr_methodPtr;
internalIntPtr_methodPtrAux;
对这三个字段做具体申明
_target
1、假如托付指向的办法是实例办法,则_target的值是指向方针办法地点工具的指针
2、假如托付指向的是静态办法,则_target的值是托付实例本身
_methodPtr
1、假如托付指向的办法是实例办法,则_methodPtr的值指向一个JITStub(假如这个办法还没有被JIT编译,关于JITStub会在前面的章节先容),或指向该办法JIT后的地点
2、假如托付指向的办法是静态办法,则_methodPtr指向的是一个Stub(一段小代码,这段代码的感化是_target,然后挪用_methodPtrAux指向的办法),并且一切署名不异的托付,共享这个Stub。为何要如许一个Stub?我想是为了让经由过程托付挪用办法的流程一致吧,不论指向的是实例办法仍是静态办法,关于内部来讲,只必要挪用_methodPtr指向的地点,可是关于挪用实例办法而言,它必要this,也就是这里的_target,而静态办法不必要,为了让这里的历程一向,CLR会悄悄的在托付指向静态办法时拔出一小段代码,用于往失落_target,而间接jmp到_methodPtrAux指向的办法。
_methodPtrAux
1、假如托付指向的是实例办法,则_methodPtrAux就是0。
2、假如托付指向的是静态办法,则这时候_methodPtrAux起的感化与_mthodPtr在托付指向实例办法的时分是一样的。
实践上经由过程反编译Delegate的代码发明,Delegate有一个只读属性Target,该Target的完成依托GetTarget办法,该办法的代码以下:
  1. 4:}3
复制代码
  1. 2:{
复制代码
  1. 4:}5
复制代码
  1. 4:}6
复制代码
  1. 4:}7
复制代码
  1. 4:}8
复制代码
  1. 4:}9
复制代码
  1. 2:{1
复制代码
实了当托付指向静态办法时,Target属性为null。
我们来本人下手,剖析一下下面的结论是不是准确。
_target和_methodPtr真的如下面所说的么?何不本人下手看看。
创建一个Console范例的工程,在项目属性的“调试(Debug)”选项卡里选中“同意非托管代码调试(Enableunmanagedcodedebuging)”。
  1. 1:namespaceYuyijq.DotNet.Chapter2
复制代码
  1. 2:{
复制代码
  1. 3:publicdelegatevoidMyDelegate(intpara);
复制代码
  1. 1:publicclassTestDelegate4
复制代码
  1. 1:publicclassTestDelegate5
复制代码
  1. 1:publicclassTestDelegate6
复制代码
  1. 1:publicclassTestDelegate7
复制代码
  1. 1:publicclassTestDelegate8
复制代码
  1. 1:publicclassTestDelegate9
复制代码
  1. 2:{0
复制代码
  1. 2:{4
复制代码
  1. 2:{2
复制代码
  1. 2:{3
复制代码
  1. 2:{7
复制代码
  1. 2:{5
复制代码
  1. 2:{6
复制代码
  1. 2:{7
复制代码
  1. 2:{8
复制代码
  1. 2:{9
复制代码
  1. 3:MyDelegatemyDelegate;0
复制代码
  1. 3:MyDelegatemyDelegate;1
复制代码
  1. 3:MyDelegatemyDelegate;2
复制代码
下面是作为实行的代码。
在CallByDelegate办法的第二行设置断点
F5实行,射中断电后,在VisualStudio的当即窗口(ImmediateWindow)里输出以下命令(菜单栏->调试(Debug)->当即窗口(Immediate)):
//.loadsos.dll用于加载SOS.dll扩大
.loadsos.dll
extensionC:WindowsMicrosoft.NETFrameworkv2.0.50727sos.dllloaded
//DumpStackObjects的缩写,输入栈中的一切工具
//该命令的输入有三列,第二列Object就是该工具在内存中的地点
!dso
PDBsymbolformscorwks.dllnotloaded
OSThreadId:0x1588(5512)
ESP/REGObjectName
0037ec10019928a4Yuyijq.DotNet.Chapter2.TestDelegate
0037ed50019928a4Yuyijq.DotNet.Chapter2.TestDelegate
0037ed5c019928b0Yuyijq.DotNet.Chapter2.MyDelegate
0037ed60019928b0Yuyijq.DotNet.Chapter2.MyDelegate
0037ef94019928b0Yuyijq.DotNet.Chapter2.MyDelegate
0037ef98019928b0Yuyijq.DotNet.Chapter2.MyDelegate
0037ef9c019928a4Yuyijq.DotNet.Chapter2.TestDelegate
0037efe0019928a4Yuyijq.DotNet.Chapter2.TestDelegate
0037efe4019928a4Yuyijq.DotNet.Chapter2.TestDelegate
//do命令为DumpObjects缩写,参数为工具地点,输入该工具的一些信息
!do019928b0
Name:Yuyijq.DotNet.Chapter2.MyDelegate
MethodTable:00263100
EEClass:002617e8
Size:32(0x20)bytes
(E:StudyDemoDemoinDebugDemo.exe)
//该工具的一些字段
Fields:
MTFieldOffsetTypeVTAttrValueName
704b84dc40000ff4System.Object0instance019928a4_target
704bd0ac40001008...ection.MethodBase0instance00000000_methodBase
704bb1884000101cSystem.IntPtr1instance0026C018_methodPtr
704bb188400010210System.IntPtr1instance00000000_methodPtrAux
704b84dc400010c14System.Object0instance00000000_invocationList
704bb188400010d18System.IntPtr1instance00000000_invocationCount
在最初Fields一部分,我们看到了_target喝_methodPtr,_target的值为019928a4,看看下面!dso命令的输入,这个不就是Yuyijq.DotNet.Chapter2.TestDelegate实例的内存地点么。
在下面的!do命令的输入中,我们看到了MethodTable:00263100,这就是该工具的办法表地点(关于办法表更具体的会商会在前面的章节先容到,如今你只需把他看作一个纪录工具一切办法的列表就好了,该列内外每个条目就是一个办法)。如今我们要看看Yuyijq.DotNet.Chapter2.TestDelegate..Test办法的内存地点,看起是不是与_methodPtr的值是分歧的,那么起首就要取得Yuyijq.DotNet.Chapter2.TestDelegate.的实例中MethodTable的值:
!do019928a4
Name:Yuyijq.DotNet.Chapter2.TestDelegate
MethodTable:00263048
EEClass:002612f8
Size:12(0xc)bytes
(E:StudyDemoDemoinDebugDemo.exe)
Fields:
None
如今晓得了其办法表的值为00263048,然后利用上面的命令找到Yuyijq.DotNet.Chapter2.TestDelegate..Test办法的地点:
!dumpmt-md00263048
EEClass:002612f8
Module:00262c5c
Name:Yuyijq.DotNet.Chapter2.TestDelegate
mdToken:02000003(E:StudyDemoDemoinDebugDemo.exe)
BaseSize:0xc
ComponentSize:0x0
NumberofIFacesinIFaceMap:0
SlotsinVTable:9
--------------------------------------
MethodDescTable
EntryMethodDescJITName
.......
0026c01000262ffcNONEYuyijq.DotNet.Chapter2.TestDelegate.AssignDelegate()
0026c0180026300cNONEYuyijq.DotNet.Chapter2.TestDelegate.Test(Int32)
......
Entry这一列就是一个JITStub。看看,公然与_methodPtr的是分歧的,由于这时候Test办法还没有经由JIT(JIT列为NONE),以是_methodPtr指向的是这里的JITStub。
假如给托付绑定一个静态办法呢?如今我们把Test办法改成静态的,那实例化托付的时分,就不克不及用this.Test了,而应当用TestDelegate.Test。仍是在原地位设置断点,利用与下面不异的命令,检察_target与_methodPtr的值。
MTFieldOffsetTypeVTAttrValueName
704b84dc40000ff4System.Object0instance01e928b0_target
704bb1884000101cSystem.IntPtr1instance007809C4_methodPtr
704bb188400010210System.IntPtr1instance0025C018_methodPtrAux
你会发明这里的_target字段的值就是MyDelegate的实例myDelegate的地点。然后我们经由过程下面的办法,找到Test办法的地点,发明_methodPtrAux的值与该值是不异的。
实践上你还能够再编写一个与MyDelegate不异署名的托付,然后也指向一个静态办法,利用不异的办法检察该托付的_methodPtr的值,你会发明这个新托付与MyDelegate的_methodPtr的值是分歧的。
方才不是说这个时分_methodPtr指向的是一个Stub么,既然云云那我们反汇编一下代码:
!u007809C4
Unmanagedcode
007809C48BC1moveax,ecx
007809C68BCAmovecx,edx
007809C883C010addeax,10h
007809CBFF20jmpdwordptr[eax]
........
.Net里JIT的办法的挪用商定是FastCall,关于FastCall来讲,办法的前两个参数会放在ECX和EDX两个存放器中。那末moveax,ecx实践上就是将_target传送给eax,再看看
704bb188400010210System.IntPtr1instance0025C018_methodPtrAux
_methodPtrAux的偏移是10,这里的addeax,10h就是将eax指向_methodPtrAux,然后jmpdwordptr[eax]就是跳转到_methodPtrAux所指向的地点了,就是托付指向的谁人静态办法。
经由过程托付挪用办法
怎样经由过程托付挪用办法呢:
  1. 3:MyDelegatemyDelegate;3
复制代码
  1. 2:{
复制代码
  1. 3:MyDelegatemyDelegate;5
复制代码
  1. 4:
复制代码
  1. 3:MyDelegatemyDelegate;7
复制代码
  1. 4:}8
复制代码
再来看看其对应的IL代码:
  1. 3:MyDelegatemyDelegate;9
复制代码
  1. 2:{
复制代码
  1. 4:1
复制代码
  1. 4:2
复制代码
  1. 4:3
复制代码
  1. 3:publicdelegatevoidMyDelegate(intpara);3
复制代码
  1. 4:5
复制代码
  1. 4:6
复制代码
  1. 4:7
复制代码
  1. 4:8
复制代码
  1. 4:9
复制代码
  1. 5:publicvoidAssignDelegate()0
复制代码
  1. 5:publicvoidAssignDelegate()1
复制代码
  1. 2:{7
复制代码
后面的代码我们已熟习,最关头的就是
callvirtinstancevoidYuyijq.DotNet.Chapter2.MyDelegate::Invoke(int32)
我们发明,经由过程托付挪用办法,实践上就是挪用托付的Invoke办法。
多播的托付
好了,既然已注释了面向工具和范例平安,那末说托付是多播的咋注释?
你大概已发明,MyDelegate承继自MulticastDelegate,看这个名字貌似有点意义了。来看看上面这两行代码:
  1. 5:publicvoidAssignDelegate()3
复制代码
  1. 5:publicvoidAssignDelegate()4
复制代码
经由过程IL我们能够发明,这里的+=最初就是挪用System.Delegate的Combine办法。而Combine的真正完成时在MulticastDelegate的CombineImpl办法中。在MulticastDelegate中有一个_invocationList字段,从CombineImpl中能够看出这个字段是一个object[]范例的,而托付链就放在这个数组里。
跋文
文章是想到哪儿写到哪儿,写的对照乱,也对照匆仓促。十分抱愧。关于两头那段奇奥的事变,我本来真的不晓得,我一向觉得当托付指向一个静态办法时,_target指向null就完事儿了,没想到另有这么一番情形。看来良多器材仍是不克不及想固然,亲自实验一下才晓得实在的情形。
你觉得学习.NET怎么样,我懂的少,问的可能很幼稚,见笑了啊:)
灵魂腐蚀 该用户已被删除
沙发
发表于 2015-1-19 10:02:40 | 只看该作者
Servlet却在响应第一个请求的时候被载入,一旦Servlet被载入,便处于已执行状态。对于以后其他用户的请求,它并不打开进程,而是打开一个线程(Thread),将结果发送给客户。由于线程与线程之间可以通过生成自己的父线程(ParentThread)来实现资源共享,这样就减轻了服务器的负担,所以,JavaServlet可以用来做大规模的应用服务。
海妖 该用户已被删除
板凳
发表于 2015-1-27 07:31:34 | 只看该作者
ASP.NET可以无缝地与WYSIWYGHTML编辑器和其他编程工具(包括MicrosoftVisualStudio.NET)一起工作。这不仅使得Web开发更加方便,而且还能提供这些工具必须提供的所有优点,包括开发人员可以用来将服务器控件拖放到Web页的GUI和完全集成的调试支持。微软为ASP.net设计了这样一些策略:易于写出结构清晰的代码、代码易于重用和共享、可用编译类语言编写等等,目的是让程序员更容易开发出Web应用,满足计算向Web转移的战略需要。
冷月葬花魂 该用户已被删除
地板
发表于 2015-2-5 04:15:10 | 只看该作者
当然我们在选择Asp.net主机是,除了要考虑服务提供商在版本是否是实时更新以外,机房的环境和配置也是非常重要的,通常选择骨干网的机房,在速度和稳定性上会非常有保证。
5#
发表于 2015-2-11 04:27:37 | 只看该作者
PHP的源代码完全公开,在OpenSource意识抬头的今天,它更是这方面的中流砥柱。不断地有新的函数库加入,以及不停地更新,使得PHP无论在UNIX或是Win32的平台上都可以有更多新的功能。它提供丰富的函数,使得在程式设计方面有着更好的资源。目前PHP的最新版本为4.1.1,它可以在Win32以及UNIX/Linux等几乎所有的平台上良好工作。PHP在4.0版后使用了全新的Zend引擎,其在最佳化之后的效率,比较传统CGI或者ASP等技术有了更好的表现。
柔情似水 该用户已被删除
6#
发表于 2015-3-11 00:35:29 | 只看该作者
ASP.net的速度是ASP不能比拟的。ASP.net是编译语言,所以,当第一次加载的时候,它会把所有的程序进行编译(其中包括worker进程,还有对语法进行编译,形成一个程序集),当程序编译后,执行速度几乎为0。
小魔女 该用户已被删除
7#
发表于 2015-3-17 17:09:35 | 只看该作者
我的意思是.net好用,从功能上来说比JAVA强还是很明显的。
活着的死人 该用户已被删除
8#
发表于 2015-3-24 14:15:47 | 只看该作者
Asp.net:首先来说,Asp.net和Asp没什么关系,看着像是升级版本什么的,其实没什么联系。Asp是脚本编程,用的是ASP语言,而ASP.net用的是C#语言,完全不同的东西。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|仓酷云 鄂ICP备14007578号-2

GMT+8, 2024-5-7 03:42

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表