Web.config详解+asp.net优化(1)
Web.config详解+asp.net优化(2)
Web.config详解+asp.net优化(3)
ASP.NET的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事件是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" onclick="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 是不是第一次加载.
每个.Net开发者现在应该下载的十个必备工具!
1.Snippet Compiler
一个短小精悍的用来编写小程序的工具;免去一段测试性质的小代码还要打开Vs.net之苦;
http://www.sliver.com/dotnet/SnippetCompiler
2.Regulator
一个功能强大的全功能正则表达式测试利器,支持从WebService取得最新的表达式;
http://royo.is-a-geek.com/regulator
3.CodeSmith
一个基于末拌的代码生成工具,使用和asp.net详细的语法生成任意类型的代码或文本;
http://www.ericjsmith.net/codesmith
4.NUnit
一个基于.net framework的开源单元测试框架;大名鼎鼎,不用多说了!
http://www.nunit.org
5.FxCop
The .NET Framework is very powerful, which means there is great potential to create
excellent applications, but there is equal opportunity to create poor programs. FxCop is one
of the tools that can be used to help create better applications by enabling you to examine
an assembly and check it for compliance using a number of different rules.
不知道怎么翻译了;高手指点一下,这个东东的用处;
http://www.gotdotnet.com/team/fxcop
6.Lutz Roeder's .NET Reflector
一个很好用的.Net下的反编译工具;具有清晰的具有层次的树试图显示程序集的各种信息;
http://www.aisto.com/roeder/dotnet
7.NDoc
方便的基于代码自动生成文档的工具;
http://ndoc.sourceforge.net
8.NAnt
又是一个Java世界的来客,基于.Net的项目管理生成工具;
http://nant.sourceforge.net
9-10.Switch Tools
切换工具,有两个功能:切换asp.net的当前使用版本,从vs.net2003的项目转换到2002的项目
http://www.denisbauer.com/NETTools/ASPNETVersionSwitcher.aspx
http://msdn.microsoft.com/msdnmag/issues/04/07/MustHaveTools/default.aspx
asp.net各文件和文件夹的作用
*.suo是项目的用户信息文件,存放用户使用Vs.Net的个人设置
*.vbproj.webinfo是Web项目特有的,包含了Web应用程序的虚拟目录等信息
*.vsdisco是动态发现文件
AssemblyInfo.vb是装配件信息文件,编译后的动态库(Assembly)里面的信息就是从这个文件中获取的
Global.asax是Web应用程序类,类似于全局函数(对应与ASP中的Global.asa)
Global.asax.resx是上面文件的资源文件
Global.asax.vb是Web应用程序类的代码绑定文件
Styles.css是样式表文件
Web.config是Web应用程序的配置文件,存放Web应用程序的各种配置
*.aspx.vb是ASPX页面文件(动态服务器页面,对应于ASP中的*.asp)
*.aspx.resx是上面这个文件的资源文件
*.aspx.vb是动态页面的代码绑定文件
程序设计模式的有趣解释
工厂模式:客户类和工厂类分开。消费者任何时候需要某种产品,只需向工厂请求即可。消费者无须修改就可以接纳新产品。缺点是当产品修改时,工厂类也要做相应的修改。如:如何创建及如何向客户端提供。
2、BUILDER—MM最爱听的就是“我爱你”这句话了,见到不同地方的MM,要能够用她们的方言跟她说这句话哦,我有一个多种语言翻译机,上面每种语言都有一个按键,见到MM我只要按对应的键,它就能够用相应的语言说出“我爱你”这句话了,国外的MM 也可以轻松搞掂,这就是我的“我爱你”builder。(这一定比美军在伊拉克用的翻译机好卖)
建造模式:将产品的内部表象和产品的生成过程分割开来,从而使一个建造过程生成具有不同的内部表象的产品对象。建造模式使得产品内部表象可以独立的变化,客户不必知道产品内部组成的细节。建造模式可以强制实行一种分步骤进行的建造过程。
3、FACTORY METHOD—请MM去麦当劳吃汉堡,不同的MM有不同的口味,要每个都记住是一件烦人的事情,我一般采用Factory?Method模式,带着MM到服务员那儿,说“要一个汉堡”,具体要什么样的汉堡呢,让MM直接跟服务员说就行了。
工厂方法模式:核心工厂类不再负责所有产品的创建,而是将具体创建的工作交给子类去做,成为一个抽象工厂角色,仅负责给出具体工厂类必须实现的接口,而不接触哪一个产品类应当被实例化这种细节。
4、PROTOTYPE—跟MM用QQ聊天,一定要说些深情的话语了,我搜集了好多肉麻的情话,需要时只要copy出来放到QQ里面就行了,这就是我的情话prototype了。(100块钱一份,你要不要)
原始模型模式:通过给出一个原型对象来指明所要创建的对象的类型,然后用复制这个原型对象的方法创建出更多同类型的对象。原始模型模式允许动态的增加或减少产品类,产品类不需要非得有任何事先确定的等级结构,原始模型模式适用于任何的等级结构。缺点是每一个类都必须配备一个克隆方法。
5、SINGLETON—俺有6个漂亮的老婆,她们的老公都是我,我就是我们家里的老公Sigleton,她们只要说道“老公”,都是指的同一个人,那就是我(刚才做了个梦啦,哪有这么好的事)
单例模式:单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例单例模式。单例模式只应在有真正的“单一实例”的需求时才可使用。
结构型模式
6、ADAPTER—在朋友聚会上碰到了一个美女Sarah,从香港来的,可我不会说粤语,她不会说普通话,只好求助于我的朋友kent了,他作为我和Sarah之间的Adapter,让我和Sarah可以相互交谈了(也不知道他会不会耍我)
适配器(变压器)模式:把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口原因不匹配而无法一起工作的两个类能够一起工作。适配类可以根据参数返还一个合适的实例给客户端。
7、BRIDGE—早上碰到MM,要说早上好,晚上碰到MM,要说晚上好;碰到MM穿了件新衣服,要说你的衣服好漂亮哦,碰到MM新做的发型,要说你的头发好漂亮哦。不要问我“早上碰到MM新做了个发型怎么说”这种问题,自己用BRIDGE组合一下不就行了
桥梁模式:将抽象化与实现化脱耦,使得二者可以独立的变化,也就是说将他们之间的强关联变成弱关联,也就是指在一个软件系统的抽象化和实现化之间使用组合/聚合关系而不是继承关系,从而使两者可以独立的变化。
8、COMPOSITE—Mary今天过生日。“我过生日,你要送我一件礼物。”“嗯,好吧,去商店,你自己挑。”“这件T恤挺漂亮,买,这条裙子好看,买,这个包也不错,买。”“喂,买了三件了呀,我只答应送一件礼物的哦。”“什么呀,T恤加裙子加包包,正好配成一套呀,小姐,麻烦你包起来。”“……”,MM都会用Composite模式了,你会了没有?
合成模式:合成模式将对象组织到树结构中,可以用来描述整体与部分的关系。合成模式就是一个处理对象的树结构的模式。合成模式把部分与整体的关系用树结构表示出来。合成模式使得客户端把一个个单独的成分对象和由他们复合而成的合成对象同等看待。
9、DECORATOR—Mary过完轮到Sarly过生日,还是不要叫她自己挑了,不然这个月伙食费肯定玩完,拿出我去年在华山顶上照的照片,在背面写上“最好的的礼物,就是爱你的Fita”,再到街上礼品店买了个像框(卖礼品的MM也很漂亮哦),再找隔壁搞美术设计的Mike设计了一个漂亮的盒子装起来……,我们都是Decorator,最终都在修饰我这个人呀,怎么样,看懂了吗?
装饰模式:装饰模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案,提供比继承更多的灵活性。动态给一个对象增加功能,这些功能可以再动态的撤消。增加由一些基本功能的排列组合而产生的非常大量的功能。
10、FACADE—我有一个专业的Nikon相机,我就喜欢自己手动调光圈、快门,这样照出来的照片才专业,但MM可不懂这些,教了半天也不会。幸好相机有Facade设计模式,把相机调整到自动档,只要对准目标按快门就行了,一切由相机自动调整,这样 MM也可以用这个相机给我拍张照片了。
门面模式:外部与一个子系统的通信必须通过一个统一的门面对象进行。门面模式提供一个高层次的接口,使得子系统更易于使用。每一个子系统只有一个门面类,而且此门面类只有一个实例,也就是说它是一个单例模式。但整个系统可以有多个门面类。
11、FLYWEIGHT—每天跟MM发短信,手指都累死了,最近买了个新手机,可以把一些常用的句子存在手机里,要用的时候,直接拿出来,在前面加上MM的名字就可以发送了,再不用一个字一个字敲了。共享的句子就是Flyweight,MM的名字就是提取出来的外部特征,根据上下文情况使用。
享元模式:FLYWEIGHT在拳击比赛中指最轻量级。享元模式以共享的方式高效的支持大量的细粒度对象。享元模式能做到共享的关键是区分内蕴状态和外蕴状态。内蕴状态存储在享元内部,不会随环境的改变而有所不同。外蕴状态是随环境的改变而改变的。外蕴状态不能影响内蕴状态,它们是相互独立的。将可以共享的状态和不可以共享的状态从常规类中区分开来,将不可以共享的状态从类里剔除出去。客户端不可以直接创建被共享的对象,而应当使用一个工厂对象负责创建被共享的对象。享元模式大幅度的降低内存中对象的数量。
12、PROXY —跟MM在网上聊天,一开头总是“hi,你好”,“你从哪儿来呀?”“你多大了?”“身高多少呀?”这些话,真烦人,写个程序做为我的Proxy吧,凡是接收到这些话都设置好了自动的回答,接收到其他的话时再通知我回答,怎么样,酷吧。?
代理模式:代理模式给某一个对象提供一个代理对象,并由代理对象控制对源对象的引用。代理就是一个人或一个机构代表另一个人或者一个机构采取行动。某些情况下,客户不想或者不能够直接引用一个对象,代理对象可以在客户和目标对象直接起到中介的作用。客户端分辨不出代理主题对象与真实主题对象。代理模式可以并不知道真正的被代理对象,而仅仅持有一个被代理对象的接口,这时候代理对象不能够创建被代理对象,被代理对象必须有系统的其他角色代为创建并传入。
行为模式
13、CHAIN?OF?RESPONSIBLEITY—晚上去上英语课,为了好开溜坐到了最后一排,哇,前面坐了好几个漂亮的MM哎,找张纸条,写上“Hi,可以做我的女朋友吗?如果不愿意请向前传”,纸条就一个接一个的传上去了,糟糕,传到第一排的M M把纸条传给老师了,听说是个老处女呀,快跑!
责任链模式:在责任链模式中,很多对象由每一个对象对其下家的引用而接
起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。客户并不知道链上的哪一个对象最终处理这个请求,系统可以在不影响客户端的情况下动态的重新组织链和分配责任。处理者有两个选择:承担责任或者把责任推给下家。一个请求可以最终不被任何接收端对象所接受。
14、COMMAND—俺有一个MM家里管得特别严,没法见面,只好借助于她弟弟在我们俩之间传送信息,她对我有什么指示,就写一张纸条让她弟弟带给我。这不,她弟弟又传送过来一个COMMAND,为了感谢他,我请他吃了碗杂酱面,哪知道他说:“我同时给我姐姐三个男朋友送COMMAND,就数你最小气,才请我吃面。”,:-(
命令模式:命令模式把一个请求或者操作封装到一个对象中。命令模式把发出命令的责任和执行命令的责任分割开,委派给不同的对象。命令模式允许请求的一方和发送的一方独立开来,使得请求的一方不必知道接收请求的一方的接口,更不必知道请求是怎么被接收,以及操作是否执行,何时被执行以及是怎么被执行的。系统支持命令的撤消。
15、INTERPRETER—俺有一个《泡MM真经》,上面有各种泡MM的攻略,比如说去吃西餐的步骤、去看电影的方法等等,跟MM约会时,只要做一个Interpreter,照着上面的脚本执行就可以了。
解释器模式:给定一个语言后,解释器模式可以定义出其文法的一种表示,并同时提供一个解释器。客户端可以使用这个解释器来解释这个语言中的句子。解释器模式将描述怎样在有了一个简单的文法后,使用模式设计解释这些语句。在解释器模式里面提到的语言是指任何解释器对象能够解释的任何组合。在解释器模式中需要定义一个代表文法的命令类的等级结构,也就是一系列的组合规则。每一个命令对象都有一个解释方法,代表对命令对象的解释。命令对象的等级结构中的对象的任何排列组合都是一个语言。
16、ITERATOR—我爱上了Mary,不顾一切的向她求婚。
Mary:“想要我跟你结婚,得答应我的条件”
我:“什么条件我都答应,你说吧”
Mary:“我看上了那个一克拉的钻石”
我:“我买,我买,还有吗?”
Mary:“我看上了湖边的那栋别墅”
我:“我买,我买,还有吗?”
Mary:“你的小弟弟必须要有50cm长”
我脑袋嗡的一声,坐在椅子上,一咬牙:“我剪,我剪,还有吗?”
……
迭代子模式:迭代子模式可以顺序访问一个聚集中的元素而不必暴露聚集的内部表象。多个对象聚在一起形成的总体称之为聚集,聚集对象是能够包容一组对象的容器对象。迭代子模式将迭代逻辑封装到一个独立的子对象中,从而与聚集本身隔开。迭代子模式简化了聚集的界面。每一个聚集对象都可以有一个或一个以上的迭代子对象,每一个迭代子的迭代状态可以是彼此独立的。迭代算法可以独立于聚集角色变化。
17、MEDIATOR—四个MM打麻将,相互之间谁应该给谁多少钱算不清楚了,幸亏当时我在旁边,按照各自的筹码数算钱,赚了钱的从我这里拿,赔了钱的也付给我,一切就OK啦,俺得到了四个MM的电话。
调停者模式:调停者模式包装了一系列对象相互作用的方式,使得这些对象不必相互明显作用。从而使他们可以松散偶合。当某些对象之间的作用发生改变时,不会立即影响其他的一些对象之间的作用。保证这些作用可以彼此独立的变化。调停者模式将多对多的相互作用转化为一对多的相互作用。调停者模式将对象的行为和协作抽象化,把对象在小尺度的行为上与其他对象的相互作用分开处理。
18、MEMENTO—同时跟几个MM聊天时,一定要记清楚刚才跟MM说了些什么话,不然MM发现了会不高兴的哦,幸亏我有个备忘录,刚才与哪个MM说了什么话我都拷贝一份放到备忘录里面保存,这样可以随时察看以前的记录啦。
备忘录模式:备忘录对象是一个用来存储另外一个对象内部状态的快照的对象。备忘录模式的用意是在不破坏封装的条件下,将一个对象的状态捉住,并外部化,存储起来,从而可以在将来合适的时候把这个对象还原到存储起来的状态。
19、OBSERVER—想知道咱们公司最新MM情报吗?加入公司的MM情报邮件组就行了,tom负责搜集情报,他发现的新情报不用一个一个通知我们,直接发布给邮件组,我们作为订阅者(观察者)就可以及时收到情报啦
观察者模式:观察者模式定义了一种一队多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化时,会通知所有观察者对象,使他们能够自动更新自己。
20、STATE—跟MM交往时,一定要注意她的状态哦,在不同的状态时她的行为会有不同,比如你约她今天晚上去看电影,对你没兴趣的MM就会说“有事情啦”,对你不讨厌但还没喜欢上的MM就会说“好啊,不过可以带上我同事么?”,已经喜欢上你的MM就会说“几点钟?看完电影再去泡吧怎么样?”,当然你看电影过程中表现良好的话,也可以把MM的状态从不讨厌不喜欢变成喜欢哦。
状态模式:状态模式允许一个对象在其内部状态改变的时候改变行为。这个对象看上去象是改变了它的类一样。状态模式把所研究的对象的行为包装在不同的状态对象里,每一个状态对象都属于一个抽象状态类的一个子类。状态模式的意图是让一个对象在其内部状态改变的时候,其行为也随之改变。状态模式需要对每一个系统可能取得的状态创立一个状态类的子类。当系统的状态变化时,系统便改变所选的子类。
21、STRATEGY—跟不同类型的MM约会,要用不同的策略,有的请电影比较好,有的则去吃小吃效果不错,有的去海边浪漫最合适,单目的都是为了得到MM的芳心,我的追MM锦囊中有好多Strategy哦。
策略模式:策略模式针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。策略模式使得算法可以在不影响到客户端的情况下发生变化。策略模式把行为和环境分开。环境类负责维持和查询行为类,各种算法在具体的策略类中提供。由于算法和环境独立开来,算法的增减,修改都不会影响到环境和客户端。
22、TEMPLATE?METHOD——看过《如何说服女生上床》这部经典文章吗?女生从认识到上床的不变的步骤分为巧遇、打破僵局、展开追求、接吻、前戏、动手、爱抚、进去八大步骤(Template method),但每个步骤针对不同的情况,都有不一样的做法,这就要看你随机应变啦(具体实现);
模板方法模式:模板方法模式准备一个抽象类,将部分逻辑以具体方法以及具体构造子的形式实现,然后声明一些抽象方法来迫使子类实现剩余的逻辑。不同的子类可以以不同的方式实现这些抽象方法,从而对剩余的逻辑有不同的实现。先制定一个*逻辑框架,而将逻辑的细节留给具体的子类去实现。
23、VISITOR—情人节到了,要给每个MM送一束鲜花和一张卡片,可是每个MM送的花都要针对她个人的特点,每张卡片也要根据个人的特点来挑,我一个人哪搞得清楚,还是找花店老板和礼品店老板做一下Visitor,让花店老板根据MM的特点选一束花,让礼品店老板也根据每个人特点选一张卡,这样就轻松多了;
访问者模式:访问者模式的目的是封装一些施加于某种数据结构元素之上的操作。一旦这些操作需要修改的话,接受这个操作的数据结构可以保持不变。访问者模式适用于数据结构相对未定的系统,它把数据结构和作用于结构上的操作之间的耦合解脱开,使得操作集合可以相对*的演化。访问者模式使得增加新的操作变的很容易,就是增加一个新的访问者类。访问者模式将有关的行为集中到一个访问者对象中,而不是分散到一个个的节点类中。当使用访问者模式时,要将尽可能多的对象浏览逻辑放在访问者类中,而不是放到它的子类中。访问者模式可以跨过几个类的等级结构访问属于不同的等级结构的成员类。
匿名委托
首先,delegate中可以注册任意多个回调,在一个delegate被调用的时候,已经注册的过程将会被逐个调用。
其次,delegate允许注册一个对象的方法,而不像 C++中指可以使用静态方法或者全局方法作为函数指针,提供了更多的灵活性,同时也暗示我们,delegate中按照某种方式保存了object的很多信息。
在 C#2.0的匿名delegate中,我们甚至可以访问当前匿名委托的上下文变量。接下来的文章中我们将会通过实际的例子,来看看强大的delegate。
首先,让我们看看在C#1.2中的一个典型的委托的写法。
public delegate void TheEvent(int a); public void test() { TheEvent testdel1 = new TheEvent(del1); testdel1(12); } public void del1(int x) { Console.WriteLine("output x : {0}", x); } |
现在我们可以写成这样:
public void test() { TheEvent testdel1 = del1; testdel1(12); } |
或者将程序改写为:
delegate void TheEvent2(int a); public void test2() { int a = 12; TheEvent ev2 = delegate(ref int x) { Console.WriteLine("output x : {0}", x); }; ev2( ref a); } |
比起1.2来,delegate的可读性更好,但是似乎没有本质的提高?慢着,让我们看看下面的例子。
public static void test3() { int a = 12; int y = 32; TheEvent ev2 = delegate(ref int x) { Console.WriteLine("output x + y : {0}", x + y); }; ev2( ref a); } |
注意,匿名函数中的内容!x + y的值被正确的输出了,而在1.2中,委托对于局部变量是没有除参数外的访问方式的。这样做有些什么好处呢?
让我们看一个更加复杂的例子:
public static void test4() { int a = 12; int y = 32; TheEvent ev2 = delegate(ref int x) { Console.WriteLine("output x + y : {0}", x + y); Thread.Sleep(100); }; //ev2(ref a); IAsyncResult ar = ev2.BeginInvoke(ref a, delegate(IAsyncResult ar2) {Console.Write("Operation finished: {0} on thread ID:{1}, is pool: {2}",ar2.IsCompleted,Thread.CurrentThread.GetHashCode(), Thread.CurrentThread.IsThreadPoolThread);} , null); Console.WriteLine("do some other calculations while counter thread is working"); Console.Write("work status : {0} Main Thread ID:{1}, is pool: {2}", ar.IsCompleted, Thread.CurrentThread.GetHashCode(), Thread.CurrentThread.IsThreadPoolThread); Thread.Sleep(500); ev2.EndInvoke(ref a, ar); } |
这个例子中使用了系统线程池对于任务进行排队,适合于IO或者计算密集型的操作的时候。使用匿名委托最大的好处在于可以完整地克隆当前运行空间上下文的可用变量,虽然这可能从另一个层面上也增加了同步的复杂度,所谓有得必有失。
AssemblyInfo.cs文件的作用
请看以下具体说明:
//备注:
[assembly:AssemblyDescription("用最强的抢劫类写成!")]
//产品名称
[assembly:AssemblyProduct("无为搜索")]
//公司
[assembly:AssemblyCompany("无为网络")]
//合法商标
[assembly:AssemblyTrademark("无为")];
//内部名称
[assembly:AssemblyCulture("")]
//设计者
[assembly:AssemblyDescription("无为类库")]
//版权
[assembly:AssemblyCopyright("Http://www.Iwbuy.Com")]
//配置文件
[assembly:AssemblyConfiguration("Configuration")]
//产品版品: 可指定,如下
// 程序集的版本信息由下列 4 个值组成:
//
// 主版本
// 次版本
// 内部版本号
// 修订号
//
// 您可以指定所有这些值,也可以使用“修订号”和“内部版本号”的默认值,方法是按
// 如下所示使用 '*':
[assembly:AssemblyVersion("1.0.*")]
生成dll文件以后再点击右键看看它的属性,你就为在里面看到熟悉的内容了:>
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) 完成对服务器回调请求。
堆和栈的区别
一、预备知识—程序的内存分配
2.3申请大小的限制
2.5堆和栈中的存储内容 2.6存取效率的比较 char s1[] = "aaaaaaaaaaaaaaa";
堆和栈的联系与区别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可是相当困难的 :) 对了,还有一件事,如果有人把堆栈合起来说,那它的意思是栈,可不是堆,呵呵, 清楚了? |
GIS书籍
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中文应用开发讲义
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,初期在准备和机遇;后期在付出。最忌优柔寡断。
委托与事件(2)
例子:
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#中把委托的作用当作是给方法的签名(包括参数类型,个数,方法的返回类型)指定名称。 委托代表了方法。
为什么说委托的类型是安全的:因为在定义委托的时候就指定了它所调用的方法的签名,所以在构造委托实例的时候会判断是否正确
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}
有些时候不用委托是很难实现某些功能的
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请求的处理所必需实现的一些系统约定。HttpHandler与HttpModule不同,一旦定义了自己的HttpHandler类,那么它对系统的HttpHandler的关系将是“覆盖”关系。
IHttpHandler如何处理HTTP请求
当一个HTTP请求经同HttpModule容器传递到HttpHandler容器中时,ASP.NET Framework会调用HttpHandler的ProcessRequest成员方法来对这个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方法来处理的。
图1:ProcessRequest方法
一个简单的HttpHandler容器
通过实现IHttpHandler接口可以创建自定义HTTP处理程序,该接口只包含两个方法。通过调用IsReusable,IHttpHandlerFactory可以查询处理程序以确定是否可以使用同一实例为多个请求提供服务。ProcessRequest方法将HttpContext实例用作参数,这使它能够访问Request和Response内部对象。在一个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
}
}
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)函数里面写代码了。
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 数据),而没有修改功能。