ASP.NET的Page_Load事件及相关转载

Page_Load,即页面载入要执行的事件; 
Page_Load的执行分为两种情况; 
1.Page_Load事件的执行是在第一次加载页面时发生(即为了响应客户的请求); 
2.Page_Load事件的执行是在把该页面回发到服务器时发生; 
ASP.NET处理重新页面的时候都要重新执行Page_Load; 
即重建Page类,而Page_Load是重建页面第一个要执行的事件; 
所以无论何种情况都会执行Page_Load,这时就有必要判断一下服务器处理Page_Load事件时是在何种情况发生; 
而Page.IsPostBack正好解决了这个问题; 
当是第一种情况的时候(为了响应客户的请求)Page.IsPostBack返回false; 
当是第二种情况的时候(把该页面回发到服务器给服务器处理时)Page.IsPostBack返回True; 
所以正确应用好Page.IsPostBack能大大的提高应用程序的性能;
 
Page_Load事件
Page_Load事件是ASP .NET识别的许多事件中的一个。Page_Load事件在一个页面加载时被触发,而且ASP .NET将自动调用Page_Load子程序,并在内部运行这段代码:

<script runat="server">
Sub Page_Load
lbl1.Text="The date and time is " & now()
End Sub
</script>
<html>
<body>
<form runat="server">
<h3><asp:label id="lbl1" runat="server" /></h3>
</form>
</body>
</html>

注意:Page_Load事件不包含对象引用或是事件参数!

--------------------------------------------------------------------------------


Page.IsPostBack属性
Page_Load子程序在每次页面加载的时候都会运行。如果你只想在第一次加载此页面的时候执行Page_Load中的代码,你可以使用Page.IsPostBack属性。如果Page.IsPostBack属性为false,页面是第一次被加载,如果为true,则页面是被“投递”(post)回服务器的(例如从一个表单中的按钮点击):

<script runat="server">
Sub Page_Load
if Not Page.IsPostBack then
lbl1.Text="The date and time is " & now()
end if
End Sub
Sub submit(s As Object, e As EventArgs)
lbl2.Text="Hello World!"
End Sub
</script>
<html>
<body>
<form runat="server">
<h3><asp:label id="lbl1" runat="server" /></h3>
<h3><asp:label id="lbl2" runat="server" /></h3>
<asp:button text="Submit" οnclick="submit" runat="server" />
</form>
</body>
</html>

上面的例子中,只会在第一次加载此页面的时候写出“The date and time is....”的消息。当用户点击Submit按钮时,submit 子程序会对第二个label写出“Hello World!”,但是第一个label中的日期和时间则不会改变。
--------------------------------------------------------------------------------


每当点击ASP.NET的Web网页上的Button、LinkButton或ImageButton等控件时,表单就会被发送到服务器上。如果某些控件的AutoPostBack属性被设置为true,那么当该控件的状态被改变后,也会使表单会发送回服务器。(AutoPostBack属性,它只有两个bool值,true/false。如果这个属性被设置成false,那么点击后就不会立刻将变化传给服务器处理,也就不会有该控件的SelectedIndexChanged事件。)   
    
     每次当表单被发送回服务器,就会被重新加载,启动Page_Load事件,执行Page_Load事件处理程序中的所有代码(注意,是每次都会执行!)。   
   很显然把网页的初始化代码放在这里是最合适不过。我们经常会希望在每次加载网页时执行一些代码,如一些控件的数据绑定。   
    
     当我们希望只有在网页第一次加载时执行另一些代码(基本上都是数据的默认绑定),甚至希望一些代码在除首次加载外的每次加载时执行。那么我们可以利用IsPostBack特性来完成这一功能。在网页第一次加载时,该属性的值是false。如果网页因回送而被重新加载,IsPostBack属性的值就会被设置为true。     
    
     在ASP.NET应用程序中,如果需要在页面第一次显示时执行一些初始化操作,必须判断IsPostBack属性!   
    
     在ASP.NET使用Page.IsPostback,那么就可以避免往返行程上的额外工作:如果处理服务器控件回发,通常需要在第一次请求页时执行代码,该代码不同于激发事件时用于往返行程的代码。如果检查?Page.IsPostBack?属性,则代码可按条件执行,具体取决于是否有对页的初始请求或对服务器控件事件的响应。这样做似乎很明显,但实际上可以忽略此项检查而不更改页的行为。该属性用的好坏,直接关系到你程序运行是否按照你最初的意愿,也关系到整个页面的效率。因为,如果每次都会给控件绑定数据,不管你是第一次访问,还是提交了数据以后,那么这个页面程序的效率可想而知。   
    
     一个B/S结构的页面每一次提交,它都会重新从头到尾执行一次。而C/S结构的程序就不会这样,这是和C/S结构的程序最大的区别!其实,得不到控件的数据,都是因为这个原因。

--------------------------------------------------------------------------------

this.IsPostBack表示是不是回发动作.所谓的回发就是在页面加载以后,在本页有提交服务器的动作.this.IsPostBack    ==    true    表示是回发.   
   通常使用this.IsPostBack    是不是第一次加载.


sharpmap AjaxMapControl分析
(一)概述
sharpmap中的ajaxmapcontrol使用asp.net 2.0提供的ICallbackEventHandler接口实现页面无刷新地图更新。

本质上ICallbackEventHandler接口底层是XMLHTTP,而XMLHTTP是当前非常热门的Ajax的基础。这也许就是sharpmap 作者将这个实现了ICallbackEventHandler接口的地图控件命名为ajaxmapcontrol 的原因吧。

ICallbackEventHandler机制是ajaxmapcontrol的核心所在。单纯从编程角度看,ICallbackEventHandler的编程比使用ms.ajax之类的开发套件编程要复杂一些。而然,ICallbackEventHandler 快捷轻量级特性,在ajaxmapcontrol样的控件中更为适用。

(二)Sharpmap AjaxMapControl 组成
ajaxmapcontrol 实际上是由两个部分组成的:一个是服务器控件;另一个是名为AjaxMap.js 客户端脚本文件。

(三)工作过程
ajaxmapcontrol 主要工作过程
1.   客户端浏览器请求带有 ajaxmapcontrol 的网页。
2.   在浏览器中,用户用鼠标操纵地图图象。鼠标的点击/拖动事件首先被来自AjaxMap.js 脚本函数截获,接着,脚本对服务器发出回调请求(WebForm_DoCallback)。这个调用采用 XMLHTTP 方式请求服务器 Generic Handler,并将鼠标交互产生的各个参数以 Get 方式发送给 Generic Handler;在调用WebForm_DoCallback 时,WebForm_DoCallback 也向 XMLHTTP 注册一个接收处理函数。
3.   在服务器上, Generic Handler 响应客户端回调请求,并根据来自客户端的参数(都是与地图图象有关的参数)生产新的地图图象。并将图象返回给客户端。
4.   XMLHTTP 利用注册的接收处理函数,将来自服务器的新的地图图象显示在页面上。

(四)说明
1.   虽然在 AjaxMapControl 实现了 ICallbackEventHandler 接口,但在服务器端真正响应客户端回调请求的并不是控件本身。服务器端响应客户请求的处理程序由 Generic Handler 完成。
2.   脚本文件是 AjaxMapControl 内嵌资源(Embedded Resource)并被编译到 DLL 中。在 AssemblyInfo.cs 加入[assembly: System.Web.UI.WebResource("SharpMap.UI.Web.UI.Ajax.AjaxMap.js", "text/javascript")],当在客户端浏览器中请求带有ajaxmapcontrol网页后,该网页就能通过 WebResource.axd 请求封入 DLL 的 AjaxMap.js 脚本文件。这样做的好处是可以在客户端缓冲该脚本文件。
3.   在浏览器中,引发脚本向服务器发出回调的操作有两个:拖动地图(Pan)操作和缩/放操作(Zoom in/out)操作;
4.   客户端脚步函数 SharpMap_BeginRefreshMap(obj,dofade)  完成对服务器回调请求。
 
堆和栈的区别
堆和栈的区别
2007-04-18 20:51

一、预备知识—程序的内存分配
一个由c/C++编译的程序占用的内存分为以下几个部分
1、栈区(stack)—      由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
2、堆区(heap) —      一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表,呵呵。
3、全局区(静态区)(static)—,全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。 - 程序结束后有系统释放 
4、文字常量区     —常量字符串就是放在这里的。 程序结束后由系统释放
5、程序代码区—存放函数体的二进制代码。
二、例子程序 
这是一个前辈写的,非常详细 
//main.cpp 
int a = 0; 全局初始化区 
char *p1; 全局未初始化区 
main() 

int b; 栈 
char s[] = "abc"; 栈 
char *p2; 栈 
char *p3 = "123456"; 123456/0在常量区,p3在栈上。 
static int c =0; 全局(静态)初始化区 
p1 = (char *)malloc(10); 
p2 = (char *)malloc(20); 
分配得来得10和20字节的区域就在堆区。 
strcpy(p1, "123456"); 123456/0放在常量区,编译器可能会将它与p3所指向的"123456"优化成一个地方。 
}


二、堆和栈的理论知识 
2.1申请方式 
stack: 
由系统自动分配。 例如,声明在函数中一个局部变量 int b; 系统自动在栈中为b开辟空间 
heap: 
需要程序员自己申请,并指明大小,在c中malloc函数 
如p1 = (char *)malloc(10); 
在C++中用new运算符 
如p2 = (char *)malloc(10); 
但是注意p1、p2本身是在栈中的。


2.2 
申请后系统的响应 
栈:只要栈的剩余空间大于所申请空间,系统将为程序提供内存,否则将报异常提示栈溢出。 
堆:首先应该知道操作系统有一个记录空闲内存地址的链表,当系统收到程序的申请时, 
会遍历该链表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲结点链表中删除,并将该结点的空间分配给程序,另外,对于大多数系统,会在这块内存空间中的首地址处记录本次分配的大小,这样,代码中的delete语句才能正确的释放本内存空间。另外,由于找到的堆结点的大小不一定正好等于申请的大小,系统会自动的将多余的那部分重新放入空闲链表中。

2.3申请大小的限制 
栈:在Windows下,栈是向低地址扩展的数据结构,是一块连续的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,在WINDOWS下,栈的大小是2M(也有的说是1M,总之是一个编译时就确定的常数),如果申请的空间超过栈的剩余空间时,将提示overflow。因此,能从栈获得的空间较小。 
堆:堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。由此可见,堆获得的空间比较灵活,也比较大。


2.4申请效率的比较: 
栈由系统自动分配,速度较快。但程序员是无法控制的。 
堆是由new分配的内存,一般速度比较慢,而且容易产生内存碎片,不过用起来最方便. 
另外,在WINDOWS下,最好的方式是用VirtualAlloc分配内存,他不是在堆,也不是在栈是直接在进程的地址空间中保留一快内存,虽然用起来最不方便。但是速度快,也最灵活。

2.5堆和栈中的存储内容 
栈: 在函数调用时,第一个进栈的是主函数中后的下一条指令(函数调用语句的下一条可执行语句)的地址,然后是函数的各个参数,在大多数的C编译器中,参数是由右往左入栈的,然后是函数中的局部变量。注意静态变量是不入栈的。 
当本次函数调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向最开始存的地址,也就是主函数中的下一条指令,程序由该点继续运行。 
堆:一般是在堆的头部用一个字节存放堆的大小。堆中的具体内容有程序员安排。

2.6存取效率的比较

char s1[] = "aaaaaaaaaaaaaaa"; 
char *s2 = "bbbbbbbbbbbbbbbbb"; 
aaaaaaaaaaa是在运行时刻赋值的; 
而bbbbbbbbbbb是在编译时就确定的; 
但是,在以后的存取中,在栈上的数组比指针所指向的字符串(例如堆)快。 
比如: 
#i nclude 
void main() 

char a = 1; 
char c[] = "1234567890"; 
char *p ="1234567890"; 
a = c[1]; 
a = p[1]; 
return; 

对应的汇编代码 
10: a = c[1]; 
00401067 8A 4D F1 mov cl,byte ptr [ebp-0Fh] 
0040106A 88 4D FC mov byte ptr [ebp-4],cl 
11: a = p[1]; 
0040106D 8B 55 EC mov edx,dword ptr [ebp-14h] 
00401070 8A 42 01 mov al,byte ptr [edx+1] 
00401073 88 45 FC mov byte ptr [ebp-4],al 
第一种在读取时直接就把字符串中的元素读到寄存器cl中,而第二种则要先把指针值读到edx中,在根据edx读取字符,显然慢了。


2.7小结: 
堆和栈的区别可以用如下的比喻来看出: 
使用栈就象我们去饭馆里吃饭,只管点菜(发出申请)、付钱、和吃(使用),吃饱了就走,不必理会切菜、洗菜等准备工作和洗碗、刷锅等扫尾工作,他的好处是快捷,但是自由度小。 
使用堆就象是自己动手做喜欢吃的菜肴,比较麻烦,但是比较符合自己的口味,而且自由度大。


下面是另一篇,总结的比上面好:

堆和栈的联系与区别dd

      在bbs上,堆与栈的区分问题,似乎是一个永恒的话题,由此可见,初学者对此往往是混淆不清的,所以我决定拿他第一个开刀。

       首先,我们举一个例子:

       void f() { int* p=new int[5]; }

       这条短短的一句话就包含了堆与栈,看到new,我们首先就应该想到,我们分配了一块堆内存,那么指针p呢?他分配的是一块栈内存,所以这句话的意思就是:在栈内存中存放了一个指向一块堆内存的指针p。在程序会先确定在堆中分配内存的大小,然后调用operator new分配内存,然后返回这块内存的首地址,放入栈中,他在VC6下的汇编代码如下:

       00401028      push           14h

       0040102A      call           operator new (00401060)

       0040102F      add            esp,4

       00401032      mov            dword ptr [ebp-8],eax

       00401035      mov            eax,dword ptr [ebp-8]

       00401038      mov            dword ptr [ebp-4],eax

       这里,我们为了简单并没有释放内存,那么该怎么去释放呢?是delete p么?澳,错了,应该是delete []p,这是为了告诉编译器:我删除的是一个数组,VC6就会根据相应的Cookie信息去进行释放内存的工作。

       好了,我们回到我们的主题:堆和栈究竟有什么区别?

       主要的区别由以下几点:

       1、管理方式不同;

       2、空间大小不同;

       3、能否产生碎片不同;

       4、生长方向不同;

       5、分配方式不同;

       6、分配效率不同;

       管理方式:对于栈来讲,是由编译器自动管理,无需我们手工控制;对于堆来说,释放工作由程序员控制,容易产生memory leak。

       空间大小:一般来讲在32位系统下,堆内存可以达到4G的空间,从这个角度来看堆内存几乎是没有什么限制的。但是对于栈来讲,一般都是有一定的空间大小的,例如,在VC6下面,默认的栈空间大小是1M(好像是,记不清楚了)。当然,我们可以修改:    

       打开工程,依次操作菜单如下:Project->Setting->Link,在Category 中选中Output,然后在Reserve中设定堆栈的最大值和commit。

注意:reserve最小值为4Byte;commit是保留在虚拟内存的页文件里面,它设置的较大会使栈开辟较大的值,可能增加内存的开销和启动时间。

       碎片问题:对于堆来讲,频繁的new/delete势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低。对于栈来讲,则不会存在这个问题,因为栈是先进后出的队列,他们是如此的一一对应,以至于永远都不可能有一个内存块从栈中间弹出,在他弹出之前,在他上面的后进的栈内容已经被弹出,详细的可以参考数据结构,这里我们就不再一一讨论了。

       生长方向:对于堆来讲,生长方向是向上的,也就是向着内存地址增加的方向;对于栈来讲,它的生长方向是向下的,是向着内存地址减小的方向增长。

       分配方式:堆都是动态分配的,没有静态分配的堆。栈有2种分配方式:静态分配和动态分配。静态分配是编译器完成的,比如局部变量的分配。动态分配由alloca函数进行分配,但是栈的动态分配和堆是不同的,他的动态分配是由编译器进行释放,无需我们手工实现。

       分配效率:栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。堆则是C/C++函数库提供的,它的机制是很复杂的,例如为了分配一块内存,库函数会按照一定的算法(具体的算法可以参考数据结构/操作系统)在堆内存中搜索可用的足够大小的空间,如果没有足够大小的空间(可能是由于内存碎片太多),就有可能调用系统功能去增加程序数据段的内存空间,这样就有机会分到足够大小的内存,然后进行返回。显然,堆的效率比栈要低得多。

       从这里我们可以看到,堆和栈相比,由于大量new/delete的使用,容易造成大量的内存碎片;由于没有专门的系统支持,效率很低;由于可能引发用户态和核心态的切换,内存的申请,代价变得更加昂贵。所以栈在程序中是应用最广泛的,就算是函数的调用也利用栈去完成,函数调用过程中的参数,返回地址,EBP和局部变量都采用栈的方式存放。所以,我们推荐大家尽量用栈,而不是用堆。

       虽然栈有如此众多的好处,但是由于和堆相比不是那么灵活,有时候分配大量的内存空间,还是用堆好一些。

       无论是堆还是栈,都要防止越界现象的发生(除非你是故意使其越界),因为越界的结果要么是程序崩溃,要么是摧毁程序的堆、栈结构,产生以想不到的结果,就算是在你的程序运行过程中,没有发生上面的问题,你还是要小心,说不定什么时候就崩掉,那时候debug可是相当困难的 :)    对了,还有一件事,如果有人把堆栈合起来说,那它的意思是栈,可不是堆,呵呵, 清楚了?

 
7月20日
GIS书籍
1.《地理信息系统开发:ArcObjects方法》

http://www.gissky.net/Soft/dzsj/200607/63.html

2. ENVI/IDL二次开发中文培训教程

http://www.gissky.net/Soft/dzsj/200607/58.html

3. ENVI用户指南(中文)

http://www.gissky.net/Soft/dzsj/200607/56.html

4. MapInfo中文版用户指南(精简版)

http://www.gissky.net/Soft/dzsj/200607/55.html

5. 数字地图制图原理

http://www.gissky.net/Soft/dzsj/200607/54.html

6. 《数字高程模型》电子书

http://www.gissky.net/Soft/dzsj/200607/45.html

7. 《Modeling Our World》中文版本

http://www.gissky.net/Soft/dzsj/200607/39.html

8. Visual C++开发GIS系统——开发实例剖析

http://www.gissky.net/Soft/dzsj/200607/38.html

9. 《地理信息系统--原理、方法和应用》

http://www.gissky.net/Soft/dzsj/200607/35.html

10. GIS二次开发-使用Mapobjects

http://www.gissky.net/Soft/dzsj/200607/28.html

11. MicroStation中文培训教材

http://www.gissky.net/Soft/dzsj/200607/25.html

12. 快速制图基本操作-ArcGIS应用案例

http://www.gissky.net/Soft/dzsj/200607/16.html

13. MapX中文应用开发讲义

http://www.gissky.net/Soft/dzsj/200607/22.html

7月19日
IBM
发信人: Windsor (微风的河岸), 信区: Career_IBM
标  题: IBM GBS的方方面面
发信站: 水木社区 (Thu Jul 19 00:04:21 2007), 站内

引子:

正式进入GBS算起来已经2年多了,一直都想说些什么,可也一直没有动笔。最终还是写了一些东西,给后来者一个参考。仅在水木清华发表,转载请注明。——Windsor@SMTH

----------------------------------------------------------------------
IBM GBS前世今生:Windsor@SMTH

2002年前,IBM的IT咨询部门是BIS(Business Innovation Services),后合并普华永道咨询部(PwCC),整合为业务咨询服务部BCS(Business Consultant Service)。合并前BIS全球5万员工,年销售102亿美元,PwCC全球3万员工,49亿美元。

IBM GBS(Global Business Service),即全球企业咨询服务部,2006年由BCS更名而来,全球最大的IT咨询公司。GBS的业务包括管理咨询,战略咨询,IT咨询等,其中前两者顾问较少,主要的定位还是一个IT咨询公司。主要竞争对手为埃森哲,凯捷,毕博,德勤咨询等。2006年所有咨询公司排名13,前几位是麦肯锡,波士顿,贝恩等管理咨询公司,略领先于科尔尼,埃森哲。

IBM IGS(Global Service)包括GBS,GTS(Global Technology Service)等,专注于IT服务。见过一个比喻,说IGS是一艘破冰船,则GBS是船头,GTS是船身,SO(Strategic Outsourcing Services等)是船尾。

----------------------------------------------------------------------
GBS多维矩阵组织结构:Windsor@SMTH

组织结构是标准的多维矩阵结构。

从Sector维度,按行业:
Public 公共事业/ Industrial 工业/ Financial 金融/ Distribution 流通/ Communications 电信/ SMB(中小企业)

从Service维度,按解决方案:
Strategy & Change 策略变更咨询/ Financial Mgmt / Supply Chain Mgmt / Customer Relationship Mgmt / Human Capital Mgmt / SAP Oracle / Application Innovation Service 应用创新服务/ Application Management Service 应用管理服务/ Application Service Delivery 应用实施

每个Services下面还有细分更具体的解决方案

从地域维度:
GBS目前仅北京,上海,广州;另外大连,上海,深圳,成都有ISSC部门。

----------------------------------------------------------------------
GBS的“带子”:Windsor@SMTH

和丐帮的“袋子”类似,按“带子”(band)来标记级别。GBS从6到10,然后依次D,C,B,A,AA。校园招聘进入GBS从Trainee(培训生)Band90(相当于Band 5.5)开始,然后半年到1年半转为Band6;Band6大概需要1到3年以上可以转为Band7;Band7需要3年以上可以转为Band8,上不封顶;Band9就很难了,Band10以上进入高管级别。

IBM Fellow算Band D,杰出工程师算Band 10。

升得快的,有7年从Trainee到Band9的,也有20年才到Band9的。高管中目前还是以台湾,香港,老外为主。升Band8不易,90级,91级,92级的本硕还有大把是Band7的。
一般本科5+年,硕士3+都会给Band7。不是特别突出者,本科或者硕士10来年也只是Band7。一般说来硕士走Trainee进入吃亏于毕业去其他公司,然后跳槽进入。

----------------------------------------------------------------------
GBS职业道路:Windsor@SMTH

常见的6种职业:Specialist,Consultant,Architect,Project Manager,Learning,Sales。

IT Specialist,也就是信息工程师,偏技术,需要对某一类IBM产品或者技术具有非常精深的认知,能够提供设计、操作、管理、维护等方面的具体工作。

IT Specialist (Band6)–>Advisory IT Specialist–>Senior IT Specialist–>Consulting IT Specialist–>Senior Consulting IT Specialist–>Executive

Consultant,咨询顾问,区分管理咨询顾问(S&C Consultant),技术咨询顾问;技术咨询顾问又细分为软件包咨询顾问(Package Consultant),和一般的技术咨询(IT Consultant)顾问。管理咨询顾问以MBA为主,负责管理咨询,战略咨询,流程咨询等。Package Consultant,负责软件产品的咨询和实施,如SAP,Oracle等。IT Consultan更侧重企业系统的整合,设计;需求分析;项目管理;软件解决方案咨询等等,很多情况下面和IT Specialist,IT Archiect并无严格区分。

Consultant (Band6)–>Senior Consultant–>Managing Consultant–>Senior Managing Consultant–>Associate Partner–>Executive

Architect,架构师。
Associate IT Archiect (Band7)–>Advisory IT Archiect–>Senior IT Archiect–>Executive IT Archiect–>Executive

Project Manager,项目经理。
Associate Project Manager (Band7)–>Advisory Project Manager–>Senior Project Manager–>Executive Project Manage–>Executive

其他的还有Learning,负责培训。Sales,包括负责服务销售和客户代表等。都很少。

----------------------------------------------------------------------
GBS技能评估体系:Windsor@SMTH

从PwCC继承过来的职业能力评价体系,PDF(Professional Development Framework),一个很不错的能力评价体系,和Band挂钩。有Core和职业两个大维度。

按职业分类6个大类的发展方向,每个发展方向细分多个子类,如Architect细分应用架构,信息架构,整合架构,企业架构,基础设施架构等。
每个方向分6个级别,1,2对应Band6,3,4,5,6分别对应Band7,8,9,10。

还有3个公共的Core方向,Business,Leadership,Relationship。每个级别分基础,有经验的,高级3个等级。Band8要求3个core全部到有经验级别,Band9以上要求3个core全部高级级别。

每年3,8月开始PDF的评估,个人提交论文,证明要求的各点已经达到,论据来源于PM审批的项目个人评估(Project Assessment)。然后老板审批,审批委员会审批则可以通过PDF的评级。然后HR审批则可以升职。

----------------------------------------------------------------------
GBS的培训:Windsor@SMTH

客观说来应该是业界培训非常好的地方。新员工有2天新员工培训,校园招聘的2周ELT(Entry Level Training),社招的1周ELT。校园招聘研究生还有2周的部门技能培训。到Band7后,每年一周的University培训。还有很多技能,沟通,演讲,项目管理,架构设计方面的培训。大概每年10天的样子。

----------------------------------------------------------------------
GBS的面包和黄油:Windsor@SMTH

1. 基本工资,一个月的工资称为MBS,一年14个月;
2. 补助800,一年12个月;
3. Perform Bonus,大概是MBS的0到80%的样子,一般50%不到。
4. 出差补助Per Diem,250每天,按过夜算,税前。对于Trainee和Band6,长期出差的Per Diem比工资更高。

Award,特别奖励,数百$的样子,很少有人得到。
每年6月根据前一年表现涨薪,比例大概0到15%的样子,一般6,7%左右。
出差可以1周到3周往返一次local,也可以选择到local更近的地点。
商务报销,每天可以报销往返客户的打车票,同客户的餐饮可以报销。
手机报销,顾问和PM每月900,一般每月500。
住房补贴Saving Fund。每月按MBS的15%累计到3年一次发放,10万封顶;不到10万,则3年后每月多发15%,到10万截止。
Band90(包括)以上均无加班工资。

年薪=MBS * 14 + 800 * 12 + Bonus(MBS * 0.5) + Per Diem(250 * day) + Award
满3年还有MBS * 15%。

这几年的Trainee行情是:
04年5200,
05年5500
06年4X00
07年5800

Band6,7,8的MBS,猜测Band6大概是6000~12000;猜测Band7大概是12000~18000;猜测band 8大概是18000~2X000。工资在招聘的时候可以谈。总体业界中等。

其中ISSC的MBS相应要下调一些,没有Saving Fund。

----------------------------------------------------------------------
GBS的投名状:Windsor@SMTH

1. 校园招聘(Campus Hire),每年秋季进入著名高校,去年开始已经暂停。管理咨询部门以MBA为主,基本都是国外的MBA和国内名校的MBA,如中欧,长江,光华,清华,复旦等。其他也以著名高校硕士为主,在京清华,北大,北邮占60%左右;上海以复旦,上交为主;广州以中山,华南理工为主。

2. 实习(Intern)。包括Blue path和Extreme blue,每年四五月份开始,通常在chinahr或者51job上会有专题。从06年开始Campus Hire停止,只在Intern中间直接招聘。

3. 社会招聘(Professinal Hire)或者猎头。如针对已经工作一年到两年的职场次新人的IBM vitality2006;和长期进行的社会招聘。

4. 推荐。内部的人推荐最有效,有熟人,尤其是推荐人本身比较厉害,可以省很多事。比如可以拿到更高的Band和更多的MBS。

5. 转。从Contract或者Sub(子包)甚至客户处转过来,Contract中的优秀者可以转,但是也控制名额。Sub中的杰出者一定会挖的。

----------------------------------------------------------------------
总结:Windsor@SMTH

工作需要有心里准备,比较苦(常加班),比较累(工作量大,且需要与时俱进更新知识),比较寂寞(长期出差)。

总之,GBS的生活是痛并快乐着。唯愿快乐和加班出差成正比,工资和双休节假休息日成反比。
----------------------------------------------------------------------
Offer选择:Windsor@SMTH
给多个师弟师妹提供过Offer选择。当初我也是懵懵懂懂就进入GBS的,所以觉得更有义务给后来者一些建议。

1.    认识行业:IT咨询很辛苦,并没有表面那么风光;IT咨询和管理咨询(如S&C)差别很大
2.    IBM内部殊途同归:同在IBM,GBS,CSDL,CRL,Sales(客户代表,渠道销售,区域销售,软件部,服务器部门,服务部门)等各有特点,选择适合个人发展的,殊途同归。GBS不一定好,CSDL测试也不差,Sales也得看是否适合个人。
3.    IT咨询,GBS和埃森哲等对手也各有专长,选择发展好,价钱高的。
4.    做技术,MS,Google,SUN,BEA,Intel,Moto等都很好,Baidu,网易等也有专长。腾讯,华为等也有专注。GBS长在宏观,短在可能不够专注。
5.    做架构师,GBS有能够使你成为IT架构师的可能,看努力,看项目,看运气,看积累。
6.    做顾问,GBS有能够锻炼你顾问能力的机会和项目,能不能做好,看性格,看项目。
7.    侯门似海,进易出难。选择一个Offer,就像选择一个GF/BF,初期在准备和机遇;后期在付出。最忌优柔寡断。
7月16日
委托与事件(2)
多播委托:委托包含多个方法。 按顺序连续调用多个方法,委托的签名必须返回void(否则,返回值应送到何处)。实际上,如果编译器发现某个委托返回void,就会自动 假定这是一个多播委托
例子:
 1 using  System;
 2
 3 namespace  test1
 4 {
 5      ///   <summary>
 6      ///  Class1 的摘要说明。
 7      /// </summary>
 8     
 9          class  MathsOperations
10          {
11              public   static   void  multiplyByTwo( double  value)
12              {
13                  double  result  =  value * 2 ;
14                 Console.WriteLine(
15                      " Multiplying by 2:{0} gives {1} " ,value,result);
16             }
17     
18              public   static   void  Square( double  value)
19              {
20                  double  result  =  value * value;
21                 Console.WriteLine(
22                      " Squareing:{0} gives {1} " ,value,result);
23             }     
24         }
25     
26          delegate   void  DoubleOp( double  value);
27     
28          class  test1
29          {
30              static   void  Main()
31              {
32                   // 或,委托可以识别 +,+=,-,-=
33                  // DoubleOp operations = new DoubleOp(MathsOperations.multiplyByTwo);
34                  // operations += new DoubleOp(MathsOperations.Square);
35
36                 DoubleOp opertaion1  =   new  DoubleOp(MathsOperations.multiplyByTwo);
37                 DoubleOp operation2  =   new  DoubleOp(MathsOperations.Square);
38                 DoubleOp operations  =  opertaion1  +  operation2;
39
40                 ProcessAndDisplayNumber(operations, 2.0 );
41                 ProcessAndDisplayNumber(operations, 40.0 );
42             }
43     
44              static   void  ProcessAndDisplayNumber(DoubleOp action, double  value)
45              {
46                 Console.WriteLine( " /nProcessAndDisplay Number called with value =  "   +
47                     value);
48                 action(value);
49             }
50         }
51 }

事件:事件与委托是密不可分的。
应用程序是通过windows来通信的,而windows又是使用预定义的消息与应用程序通信的。微软已经定义好了N多个系统事件(消息),譬如点击一个摁钮,打开一个下拉框,等等。 事件接收器就是指发生某事件时被通知的任何应用程序,对象或组件。 事件发送器可以是应用程序的一个对象或程序集。系统事件中如鼠标单击,键盘按键 。.net程序中的事件发送器就是.net的运行库,.net framework把windows消息封装在了事件中,偶没学过windows编程,对windows消息的机制不甚了解。大概就是button的click事件封装了windows的WM_MOUSECLICK消息。然后就可以直接调用click事件了。
button1.click  += new EventHandler(Button_Click);
事件              +=    实例化一个委托(某个方法)   //可多个方法依次添加到委托列表,但不能保证调用时方法的顺序。
EventHandler 委托在Farmework是已定义的,位于System命名空间,在所有的Farmework中的定义的事件都是用它。添加到该委托列表的方法都必须有相同的签名。private void Button_Click(object sender , Eventargs e) //1参:引发事件的对象,2参:包含有关事件的其他有用信息的对象,可任意类型,只要派生于它均可,譬如MouseDownEventArgs 类型。

委托和事件在用户界面程序里用的比较的多,比如象在winform或webform的用户UI上的button和它的click事件:

// 将Button1_Click()方法绑定到按钮控件Button1的Click事件上

this.Button1.Click += new System.EventHandler(this. Button1_Click);

private void Button1_Click(object sender, System.EventArgs e)    // Button1_Click()方法

{

                …… 

}

然而除了用户界面程序外,在很多其他地方也用到了事件驱动模式,比如观察者模式(Observer)或发布/订阅(Publish/Subscribe)里:在一个类里发布(Publish)某个可以被触发的事件,而其他的类就可以来订阅(Subscribe)该事件。一旦这个发布者类触发了该事件,那么运行时环境会立刻告知所有订阅了该事件的订阅者类:这个事件发生了!从而各个订阅者类可以作出它们自己的反应(调用相应方法)。

 

委托与事件(1)
委托:譬如别人 委托你买你去书挑选一本好的c#的书,而你却因为懒得动,直接去了dearbook选书,然后送上门。然后你转交给了朋友。这就是现实中的委托。-------你的好朋友并不知道,你没有去书店选。(不关注方法的细节)
c#中把委托的作用当作是给方法的签名(包括参数类型,个数,方法的返回类型)指定名称。 委托代表了方法。
为什么说委托的类型是安全的:因为在定义委托的时候就指定了它所调用的方法的签名,所以在构造委托实例的时候会判断是否正确

 2 using  System;
 3
 4 namespace  test1
 5 {
 6   ///   <summary>
 7   ///  Class1 的摘要说明。
 8   ///   </summary>
 9  
10   class  MathsOperations
11   {
12    public   static   double  multiplyByTwo( double  value)
13    {
14     return  value * 2 ;
15   }
16
17    public   static   double  Square( double  value)
18    {
19     return  value * value;
20   }
21  }
22
23   delegate   double  DoubleOp( double  x);
24
25   class  test1
26   {
27    static   void  Main()
28    {
29    DoubleOp[] operations  =
30      {
31       new  DoubleOp(MathsOperations.multiplyByTwo),
32       new  DoubleOp(MathsOperations.Square)
33     } ;
34
35     for ( int  i = 0 ;i < operations.Length;i ++ )
36     {
37     Console.WriteLine( " Using operations[{0}]; " ,i);
38     ProcessAndDisplayNumber(operations[i], 2.0 );
39     ProcessAndDisplayNumber(operations[i], 5 );
40     Console.WriteLine();
41    }
42   }
43
44    static   void  ProcessAndDisplayNumber(DoubleOp action, double  value)
45    {
46     double  result  =  action(value);
47    Console.WriteLine( " Value is {0},result of operation is {1} " ,value,result);
48   }
49  }
50  
51
52 }

有些时候不用委托是很难实现某些功能的 
 1      class BubbleSorter
 2     {
 3          static  public  void Sort( object[] sortArray,CompareOp gtMethod)
 4         {
 5              for( int i=0;i<sortArray.Length;i++)
 6             {
 7                  for( int j=i+i;i<sortArray.Length;j++)
 8                 {
 9                      if(gtMethod(sortArray[j],sortArray[i]))
10                     {
11                          object temp = sortArray[i];
12                         sortArray[i] = sortArray[j];
13                         sortArray[j] = temp;
14                     }
15                 }
16             }
17         }
18     }
19
20      delegate  bool CompareOp( object lhs, object rhs);
21
22      class Employee
23     {
24          private  string name;
25          private  decimal salary;
26
27          public Employee( string name, decimal salary)
28         {
29              this.name=name;
30              this.salary=salary;
31         }
32          public  override  string ToString()
33         {
34              return  string.Format(name + ",{0:c}",salary);
35         }
36          public  static  bool RhslsGreater( object lhs, object rhs)
37         {
38             Employee empLhs = (Employee)lhs;
39             Employee empRhs = (Employee)rhs;
40              return(empLhs.salary>empRhs.salary)? true: false;
41         }
42     }
43
44
45      class test1
46     {
47          static  void Main()
48         {
49             Employee [] employees = 
50             {
51                  new Employee("abc",100),
52                  new Employee("bbc",122),
53                  new Employee("bb",111),
54             };
55
56
57             CompareOp employeeCompareOp =  new CompareOp(Employee.RhslsGreater);
58             BubbleSorter.Sort(employees,employeeCompareOp);
59
60              for( int i=0;i<employees.Length;i++)
61             {
62                 Console.WriteLine(employees[i].ToString());
63             }
64         }
65     }
66 }

ASP.NET必须知道的东东

asp.net架构

一 asp.net请求的处理过程
-------------------
HttpModule  必须要掌握的东西
HttpHandler 必须要掌握的东西,非常有用
以上两个的实例
---------------------
asp.net 事件模型机制

-----------------------

客户的请求页面由aspnet_isapi.dll这个动态连接库来处理,把请求的aspx文件发送给CLR进行编译执行,然后把Html流返回给浏览器
--------------------------
二 页面事件
执行顺序
Page_Init:初始化值或连接
Page_Load:主要使用IsPostBack,该事件主要执行一系列得操作来首次创建asp.net页面或响应
由投递引起得客户端事件。在此事件之前,已还原页面和控件视图状态。
Page_DataBind:在页面级别上调用,也可在单个控件中调用。
DataBind_PreRender:数据绑定预呈现,恰好在保存视图状态和呈现控件之前激发此事件。
Page_Unload:此事件是执行最终清理工作的。
非确定事件
Page_Error:如果在页面处理过程中出现未处理的例外,则激发error事件。
Page_AbortTransaction:交易事件,事务处理中如果已终止交易,则激发此事件,购物车常用。
Page_CommitTransaction:如果已成功交易,则激发此事件。
--------------------------------------------------------
Global.asax中的事件(执行顺序)
Application_Start:应用程序启动时激发
Application_BeginRquest:http请求开始时激发
Application_AuthenticateRequest:  应用程序批准http请求时激发
Session_Start: 会话启动时激发
Application_EndRequest:Htttp请求结束时激发
Session_End:会话结束时激发
Application_End:应用程序结束时激发
Application_Error: 发生错误时激发
----------------------
ISAPI: 向web服务器插入某些组建,扩展功能,增强web服务器功能。
ISAPI: 扩展,win32的动态链接库,譬如aspnet_isapi.dll,可以把ISAPI扩展看作是一个普通的应用程序,它处理的目标是HTTP请求。
ISAPI: 过滤器,web服务器把请求传递给相关的过滤器,接下来过滤器可能修改请求,执行某些操作等等。
ASP.NET请求的处理过程:
基于管道模型,在模型中ASP.NET把http请求传递给管道中所有的模块。每个模块都接收HTTP请求,并有完全的控制权。一旦请求经过了所有的HTTP模块,最终被HTTP处理程序处理。HTTP处理程序对请求进行一些处理,并且结果将再次经过模块管道中的HTTP模块。
-----------
httpmodule 
ISAPI过滤器(筛选器):IIS本身是不支持动态页面的,也就是说他仅仅支持静态HTML页面的内容,对于.asp .aspx .cgi .php等,IIS并不知道如果处理这些后缀标记,它就会把它当作文本,丝毫不做处理发送到客户端。为了解决这个问题,IIS有一种机制,叫做ISAPI的过滤器。它是一个COM组件。
ASP.NET服务在注册到IIS的时候,会把每个扩展可以处理的文件扩展名注册到IIS里面(如*.ascx *.aspx等)。扩展启动后,就根据定义好的方式来处理IIS所不能处理的文件,然后把控制权跳转到专门处理代码的进程中,asp.net中是aspnet_isapi.dll。让这个进程开始处理代码,生成标准的HTML代码,生成后把这些代码加入到原有的HTML中,最后把完整的HTML返回给IIS,IIS再把内容发送到客户端。
----------------
HttpModule
Http模块实现了过滤器(ISAPI filter)的功能,它是实现了System.Web.IHttpModule接口的.net组件。。这些组件通过在某些事件中注册自身,把自己插入到ASP.NET请求处理管道。当这些事件发生的时候,ASP.NET调用对请求有兴趣的HTTP模块,这样该模块就能处理请求了。有时候需要过虑一下http请求,注意它不是覆盖其他的包括系统自带的HttpModule,在Machine.config中配置完成。
--------------------------------------
HttpHandler
它实现了ISAPI Extention的功能,它处理请求(Request)的信息和发送响应(Response)。HttpHandler功能的通过必须实现IHttpHandler接口。HTTP处理程序是实现System.Web.IHttpHandler接口的.NET组件。任何实现了该接口的类都可以用于处理输入的Http请求。它就是Http处理程序。

在以前的ASP时候,当请求一个*.asp页面文件的时候,这个HTTP请求首先会被一个名为inetinfo.exe进程所截获,这个进程实际上就是www服务。截获之后它会将这个请求转交给asp.dll进程,这个进程就会解释这个asp页面,然后将解释后的数据流返回给客户端浏览器。其实ASP.DLL是一个依附在IIS的ISAPI文件,它负责了对诸如ASP文件,ASA等文件的解释执行,
-------------------------------------


ASP.NET的HTTP请求处理方法
当客户端向web服务器请求一个*.aspx的页面文件时,同asp类似,这个http请求也会被inetinfo.exe进程截获(www服务),它判断文件后缀之后,把这个请求转交给ASPNET_ISAPI.DLL而ASPNET_ISAPI.DLL则会通过一个Http PipeLine的管道,将这个http请求发送给ASPNET_WP.EXE进程,当这个HTTP请求进入ASPNET_WP.EXE进程之后,asp.net framework就会通过HttpRuntime来处理这个Http请求,处理完毕后将结果返回给客户端。
------------------------------------
当一个http请求被送入到HttpRuntime之后,这个Http请求会继续被送入到一个被称之为HttpApplication Factory的一个容器当中,而这个容器会给出一个HttpApplication实例来处理传递进来的http请求,而后这个Http请求会依次进入到如下几个容器中:
HttpModule --> HttpHandler Factory --> HttpHandler
当系统内部的HttpHandler的ProcessRequest方法处理完毕之后,整个Http Request就被处理完成了,客户端也就得到相应的东东了。
完整的http请求在asp.net framework中的处理流程:
HttpRequest-->inetinfo.exe->ASPNET_ISAPI.DLL-->Http Pipeline-->ASPNET_WP.EXE-->HttpRuntime-->HttpApplication Factory-->HttpApplication-->HttpModule-->HttpHandler Factory-->HttpHandler-->HttpHandler.ProcessRequest()
如果想在中途截获一个httpRequest并做些自己的处理,就应该在HttpRuntime运行时内部来做到这一点,确切的说时在HttpModule这个容器中做到这个的。
----------------------------------------
-------------------------------------
系统本身的HttpModule实现一个IHttpModule的接口,当然我们自己的类也能够实现IHttpModule接口,这就可以替代系统的HttpModule对象了。
ASP.NET系统中默认的HttpModule:

DefaultAuthenticationModule  确保上下文中存在 Authentication 对象。无法继承此类。 
FileAuthorizationModule  验证远程用户是否具有访问所请求文件的 NT 权限。无法继承此类。 
FormsAuthenticationModule 启用 ASP.NET 应用程序以使用 Forms 身份验证。无法继承此类。 
PassportAuthenticationModule  提供环绕 PassportAuthentication 服务的包装。无法继承此类。 
SessionStateModule   为应用程序提供会话状态服务。 
UrlAuthorizationModule   提供基于 URL 的授权服务以允许或拒绝对指定资源的访问。无法继承此类。 
WindowsAuthenticationModule  启用 ASP.NET 应用程序以使用 Windows/IIS 身份验证。无法继承此类

--------------------------------------
这些系统默认的HttpModule是在文件machine.config中配置的,和我们开发时使用到的web.config的关系是:是在ASP.NET FRAMEWORK启动处理一个Http Request的时候,它会依次加载machine.config和请求页面所在目录的web.config文件,如果在machine中配置了一个自己的HttpModule,你仍然可以在所在页面的web.config文件中remove掉这个映射关系。
public class HelloWorldModule : IHttpModule
{
    public HelloWorldModule()
    {
    }

    public String ModuleName
    {
        get { return "HelloWorldModule"; }
    }

    // In the Init function, register for HttpApplication 
    // events by adding your handlers.
    public void Init(HttpApplication application)
    {
        application.BeginRequest += 
            (new EventHandler(this.Application_BeginRequest));
        application.EndRequest += 
            (new EventHandler(this.Application_EndRequest));
    }

    private void Application_BeginRequest(Object source, 
         EventArgs e)
    {
    // Create HttpApplication and HttpContext objects to access
    // request and response properties.
        HttpApplication application = (HttpApplication)source;
        HttpContext context = application.Context;
        context.Response.Write("<h1><font color=red> HelloWorldModule: Beginning of Request</font></h1><hr>");
    }

    private void Application_EndRequest(Object source, EventArgs e)
    {
        HttpApplication application = (HttpApplication)source;
        HttpContext context = application.Context;
        context.Response.Write("<hr><h1><font color=red>HelloWorldModule: End of Request</font></h1>");
    }

    public void Dispose()
    {
    }
}

    <system.web>
  <httpModules>
   <add name="HelloWorldModule" type="HelloWorldModule"/>
  </httpModules>
    </system.web>
-----------------------------------------------------------------------------------
深入HttpModule
一个Http请求在被ASP.NET Framework捕获之后会依次交给HttpModule以及HttpHandler来处理。hm与hh之间不是完全独立的,实际上,http请求在hm传递的过程中会在某个事件内将控制权转交给hh的,而真正的处理在HttpHandler中执行完成后,HttpHandler会再次将控制权交还给HttpModule
上面的代码中的HttpModule的Init()中的参数是HttpApplication类型,它具有许多事件,包括BeginRequest,EndRequest,AuthentiacteRequest 等等。
-----------------------------------------------------------------
IHttpHandler
它是asp.net Framework提供的一个接口,定义了如果要实现一个Http请求的处理所需要必须实现的一些系统约定。也就是说,如果你想要自行处理某些类型的HTTP请求信息流的话,你需要实现这些系统约定才能做到。譬如一个*.aspx文件,用来处理此类型的Http请求,ASP.NET FRAMEWORK将会交给一个名为System.Web.UI.PageHandlerFactory的HttpHandler类来处理。
HH和HM一样,系统会在最初始由ASP.NET FRAMEWORK首先加载machine.config中的HttpHandler,而后会加载Web应用程序所在目录的web.config中的用户自定义的HttpHandler类。但是系统与我们自定义的HH之间的关系是"覆盖"的,也就是说如果我们自定义了一个针对"*.aspx"的HttpHandler类的话,那么系统会将对此http请求的处理权完全交给我们自己定义的这个HttpHandler类来处理,而我们自己的HttpHandler类则需要自己完全解析这个Http请求,并作出处理。
IHttpHandler接口中最重要的方法ProcessRequest,这个方法就是HttpHandler用来处理一个Http请求,当一个Http请求经过由HttpModule容器传递到HttpHandler容器中的时候,framework会调用HttpHandler的ProcessRequest方法来做对这个Http请求做真正的处理。
framework实际上并不是直接把相关页面的HTTP请求定位到一个内部默认的IHttpHandler容器之上的,而是定位到了其 内部默认的IHttpHandler Factory上了。IHttpHandler Factory的作用就是对很多系统已经实现了的IHttpHandler容器进行调度和管理的,这样做的优点是大大增强了系统的负荷性,提升了效率。

HttpHandler
概述

HttpHandler是一个HTTP请求的真正处理中心,也正是在这个HttpHandler容器中,ASP.NET Framework才真正地对客户端请求的服务器页面做出编译和执行,并将处理过后的信息附加在HTTP请求信息流中再次返回到HttpModule中。

IHttpHandler是什么

IHttpHandler定义了如果要实现一个HTTP请求的处理所必需实现的一些系统约定。HttpHandlerHttpModule不同,一旦定义了自己的HttpHandler类,那么它对系统的HttpHandler的关系将是“覆盖”关系。

IHttpHandler如何处理HTTP请求

当一个HTTP请求经同HttpModule容器传递到HttpHandler容器中时,ASP.NET Framework会调用HttpHandlerProcessRequest成员方法来对这个HTTP请求进行真正的处理。以一个ASPX页面为例,正是在这里一个ASPX页面才被系统处理解析,并将处理完成的结果继续经由HttpModule传递下去,直至到达客户端。

对于ASPX页面,ASP.NET Framework在默认情况下是交给System.Web.UI.PageHandlerFactory这个HttpHandlerFactory来处理的。所谓一个HttpHandlerFactory,所谓一个HttpHandlerFactory,是指当一个HTTP请求到达这个HttpHandler Factory时,HttpHandlerFactory会提供出一个HttpHandler容器,交由这个HttpHandler容器来处理这个HTTP请求。

一个HTTP请求都是最终交给一个HttpHandler容器中的ProcessRequest方法来处理的。


1ProcessRequest方法


一个简单的
HttpHandler容器

通过实现IHttpHandler接口可以创建自定义HTTP处理程序,该接口只包含两个方法。通过调用IsReusableIHttpHandlerFactory可以查询处理程序以确定是否可以使用同一实例为多个请求提供服务。ProcessRequest方法将HttpContext实例用作参数,这使它能够访问RequestResponse内部对象。在一个HttpHandler容器中如果需要访问Session,必须实现IRequiresSessionState接口,这只是一个标记接口,没有任何方法。


示例
1

using System;

using System.Collections.Generic;

using System.Text;

using System.Web;

using System.Web.SessionState;

namespace MyHandler

{

    /// <summary>

    /// 目的:实现一个简单的自定义HttpHandler容器

    /// 作者:文野

    /// 联系:stwyhm@cnblogs.com

    /// </summary>

    public class MyFirstHandler : IHttpHandler,IRequiresSessionState

    {

        #region IHttpHandler 成员

        public bool IsReusable

        {

            get { return true; }

        }

        public void ProcessRequest(HttpContext context)

        {

            context.Response.Write("<h1><b>Hello HttpHandler</b></h1>");

            context.Session["Test"] = "测试HttpHandler容器中调用Session";

            context.Response.Write(context.Session["Test"]);

        }

        #endregion

    }

}

Web.config中加入如下配置:

<httpHandlers>

     <add verb="*" path="*" type="MyHandler.MyFirstHandler, MyHandler"/>

</httpHandlers>


 

IHttpHandler工厂

ASP.NET Framework实际不直接将相关的页面资源HTTP请求定位到一个其内部默认的IHttpHandler容器之上,而定位到了其内部默认的IHttpHandler工厂上。IHttpHandler工厂的作用是对IHttpHandler容器进行调度和管理。

IHttpHandlerFactory接口包含两个方法。GetHandler返回实现IHttpHandler接口的类的实例,ReleaseHandler使工厂可以重用现有的处理程序实例。

示例2

using System;

using System.Collections.Generic;

using System.Text;

using System.Web;

namespace MyHandler

{

    public class MyHandlerFactory : IHttpHandlerFactory

    {

        #region IHttpHandlerFactory 成员

        public IHttpHandler GetHandler(HttpContext context, string requestType, string url, string pathTranslated)

        {

            string fname = url.Substring(url.IndexOf('/') + 1);

            while (fname.IndexOf('/') != -1)

                fname = fname.Substring(fname.IndexOf('/') + 1);

            string cname = fname.Substring(0, fname.IndexOf('.'));

            string className = "MyHandler." + cname;

            object h = null;

            try

            {

                // 采用动态反射机制创建相应的IHttpHandler实现类。

                h = Activator.CreateInstance(Type.GetType(className));

            }

            catch (Exception e)

            {

                throw new HttpException("工厂不能为类型"+cname+"创建实例。",e);

            }

            return (IHttpHandler)h;

        }

        public void ReleaseHandler(IHttpHandler handler)

        {

           

        }

        #endregion

    }

    public class Handler1 : IHttpHandler

    {

        #region IHttpHandler 成员

        public bool IsReusable

        {

            get { return true; }

        }

        public void ProcessRequest(HttpContext context)

        {

            context.Response.Write("<html><body><h1>来自Handler1的信息。</h1></body></html>");

        }

        #endregion

    }

    public class Handler2 : IHttpHandler

    {

        #region IHttpHandler 成员

        public bool IsReusable

        {

            get { return true; }

        }

        public void ProcessRequest(HttpContext context)

        {

            context.Response.Write("<html><body><h1>来自Handler2的信息。</h1></body></html>");

        }

        #endregion

    }

}



6月22日
SharpMap表现层控件 扩展分析

转载

Sharpmap 作为优秀的基于vs2005的GIS解决方案,大家也对其了解甚多,我就不多说了。在实际使用中,特别是web控件,作者并没有暴露很多编程方法,本文基于此进行讨论。

在项目开发中,我们希望在鼠标拖拽时起码要实现几个功能:平移、拉框缩放、拉框选择。通过更改Sharpmap.UI.dll的方式修改,可以实现。

首先,增加鼠标拖拽选择模式属性MouseMode,并增加enum,代码形如:
public enum eMouseMode
        {
            Pan,
            Zoom,
            Select
        }
        private eMouseMode _MouseMode;

        /** <summary>
        /// Set Mouse down,up, move event to pan or zoom mode
        /// </summary>
        [Category("Behavior")]
        [DefaultValue(0)]
        [Description("设置鼠标拖拽方式:即设置Mousedown,Mousemove,Mouseup事件的处理方式。默认值为Pan。")]
        public eMouseMode MouseMode
        {
            get { return _MouseMode; }
            set { _MouseMode = value; }
        }

其次,将属性暴露给JS,让客户端可以调用。

       通过修改GenerateClientScripts函数,增加setvarsScript变量定义。

拉框需要有html控件,我这里使用div。

首先,在GenerateMapBox函数中生成控件,使用Controls.add方法增加进来。

其次,在JS中注册。

       通过修改JS文件的SharpMap_Init函数和CS文件的GenerateClientScripts函数,将增加的控件暴露给JS使用。

至此我们在前后台均可以使用新增加的控件和方法。然后,就可以在SharpMap_MouseDown(Up, Over)函数里面写代码了。

6月14日
SharpMap深度分析之数据源

SharpMap 深度分析之数据源
■ 文/Mars
在《3s 新闻周刊》的第一期对SharpMap 源码做了一个走马观花式的分析,没有深入一
些细节性的东西,本文则就数据源的问题作一些深入分析。
在SharpMap 中,数据的获取使用了数据Provider。Provider 或者Provider 模式对于很多
人应该都不陌生,在DNN 和Asp.net 2.0 中都大量应用了Provider 模式。目前主流的GIS 平
台的数据提供也应该基本上都是基于Provider 这样的模式,大家比较熟悉的应该是SuperMap
提出的多源空间数据引擎的概念。
在SharpMap 里,数据Provider 是这样使用的:
string ConnStr =
"Server=127.0.0.1;Port=5432;UserId=postgres;Password=password;Database=my
GisDb;";
myLayer.DataSource = new SharpMap.Providers.PostGIS(ConnStr, "myTable",
"the_geom", 32632);
而实际上,在Layer 类里,DataSource 定义为:
public SharpMap.Data.Providers.IProvider DataSource
{
...
}
也就是说,这里的Provider 是针对IProvider 接口编程的,这样,对于不同的层,你可
以指定不同的数据源(通过使用不同的数据Provider,而支持不同的数据格式)。下面是
Provider 接口的类图,定义了接口的属性和操作:

 

个人认为,Provider 的核心思想在于面向接口编程,也就是说通过接口定义需要的服务,
至于服务的实现,可以通过具体的方式来实现。就GIS 数据引擎来说,就是定义对空间数
据需要的操作,例如打开、关闭、读取某个范围内的数据,以及数据的检索、分析等等接口,
然后通过实现该接口来实现对不同格式数据的支持。例如对Shape 文件的操作和对PostGIS
文件的操作是完全不同的,但各自的Provider 都实现了IProvider 接口。在SharpMap 系统内
部,对数据的操作,例如放大缩小、变换、显示,只需要针对接口(IProvider)编程,而无
须关心数据的具体格式,而实现对不同格式数据源的支持。其结构大概如下图所示。
      


 

熟悉SuperMap 的朋友可以发现这个结构和超图的多源空间数据引擎的概念如出一辙。
这里的空间数据Provider 实现和ASP.net 中的DNN 等的Provider 模式的不同在于,DNN
是通过配置文件和反射机制,来实现不同的Provider 的更换,而无须更改代码实现(客户代
码),而SharpMap 或其他GIS 的类似实现是需要在开发时指定使用的Provider。前者的好处

在于使用系统的客户代码在编译部署以后,也可以动态更换,增加新的数据引擎。
Provider 的实现还有一个比较重要的问题就是要操作的数据的定义,也就是系统内部的
空间数据格式的问题。因为具体的Provider 的实现最终要将数据转换为系统内部的数据类型
和结构,然后返回。
对于具体的Geometry 的结构,SharpMap 是在OGC 的规范的基础上实现的。对于这部
分内容,很多面向对象的书也喜欢用空间几何对象、圆、正方形、线段等等来讲述类、对象、
继承等概念,大家都很熟悉,这里就不多说了。对OGC 的Simple Feature 实现比较好的一
个.net 类库是NTS(JTS 的.net 移植版本),目前正在看他的源码,后面会写一些自己的笔记。
SharpMap 的一些代码,从其注释来看也是在NTS 的基础上实现的。
SharpMap 的Provider 没有定义数据的修改、编辑,从理论上讲,完全可以实现任意数
据的读取、修改,但实际上,数据的读取显示一般来说实现难度不是很大,因为空间对象不
外乎点、线、面及其组合这样的对象;但由于内部数据结构、拓扑关系、索引等问题,修改、
编辑就比较困难了。例如SuperMap 的产品也只是可以只读读取一些其他格式的数据(如
MicroStation DGN,AutoCAD 数据),而没有修改功能。

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值