C#的疑问

一个C#睡前故事

从 前,在南方一块奇异的土地上,有个工人名叫彼得,他非常勤奋,对他的老板总是百依百顺。但是他的老板是个吝啬的人,从不信任别人,坚决要求随时知道彼得的 工作进度,以防止他偷懒。但是彼得又不想让老板呆在他的办公室里站在背后盯着他,于是就对老板做出承诺:无论何时,只要我的工作取得了一点进展我都会及时 让你知道。彼得通过周期性地使用“带类型的引用”(原文为:“typed reference” 也就是delegate??)“回调”他的老板来实现他的承诺,如下:

接口

现在,彼得成了一个特殊的人,他不但能容忍吝啬的老板,而且和他周围的宇宙也有了密切的联系,以至于他认为宇宙对他的工作进度也感兴趣。不幸的是,他必须也给宇宙添加一个特殊的回调函数Advise来实现同时向他老板和宇宙报告工作进度。彼得想要把潜在的通知的列表和这些通知的实现方法分离开来,于是他决定把方法分离为一个接口:

委托

不幸的是,每当彼得忙于通过接口的实现和老板交流时,就没有机会及时通知宇宙了。至少他应该忽略身在远方的老板的引用,好让其他实现了IWorkerEvents的对象得到他的工作报告。(”At least he’d abstracted the reference of his boss far away from him so that others who implemented the IWorkerEvents interface could be notified of his work progress” 原话如此,不理解到底是什么意思:))

他的老板还是抱怨得很厉害。“彼得!”他老板吼道,“你为什么在工作一开始和工作进行中都来烦我?!我不关心这些事件。你不但强迫我实现了这些方法,而且还在浪费我宝贵的工作时间来处理你的事件,特别是当我外出的时候更是如此!你能不能不再来烦我?”

于是,彼得意识到接口虽然在很多情况都很有用,但是当用作事件时,“粒度”不够好。他希望能够仅在别人想要时才通知他们,于是他决定把接口的方法分离为单独的委托,每个委托都像一个小的接口方法:

静态监听者

这样,彼得不会再拿他老板不想要的事件来烦他老板了,但是他还没有把宇宙放到他的监听者列表中。因为宇宙是个包涵一切的实体,看来不适合使用实例方法的委托(想像一下,实例化一个“宇宙”要花费多少资源…..),于是彼得就需要能够对静态委托进行挂钩,委托对这一点支持得很好:

事件

不幸的是,宇宙太忙了,也不习惯时刻关注它里面的个体,它可以用自己的委托替换了彼得老板的委托。这是把彼得的Worker类的的委托字段做成public的一个无意识的副作用。同样,如果彼得的老板不耐烦了,也可以决定自己来激发彼得的委托(真是一个粗鲁的老板):

彼得不想让这些事发生,他意识到需要给每个委托提供“注册”和“反注册”功能,这样监听者就可以自己添加和移除委托,但同时又不能清空整个列表也不能随意激发彼得的事件了。彼得并没有来自己实现这些功能,相反,他使用了event关键字让C#编译器为他构建这些方法:

彼得知道event关键字在委托的外边包装了一个property,仅让C#客户通过+= 和 -=操作符来添加和移除,强迫他的老板和宇宙正确地使用事件。

收获所有结果

到这时,彼得终于可以送一口气了,他成功地满足了所有监听者的需求,同时避免了与特定实现的紧耦合。但是他注意到他的老板和宇宙都为它的工作打了分,但是他仅仅接收了一个分数。面对多个监听者,他想要“收获”所有的结果,于是他深入到代理里面,轮询监听者列表,手工一个个调用:

异步通知:激发 & 忘掉

同时,他的老板和宇宙还要忙于处理其他事情,也就是说他们给彼得打分所花费的事件变得非常长:

很不幸,彼得每次通知一个监听者后必须等待它给自己打分,现在这些通知花费了他太多的工作事件。于是他决定忘掉分数,仅仅异步激发事件:

异步通知:轮询

这使得彼得可以通知他的监听者,然后立即返回工作,让进程的线程池来调用这些代理。随着时间的过去,彼得发现他丢失了他工作的反馈,他知道听取别人的赞扬和努力工作一样重要,于是他异步激发事件,但是周期性地轮询,取得可用的分数。

异步通知:委托

不幸地,彼得有回到了一开始就想避免的情况中来,比如,老板站在背后盯着他工作。于是,他决定使用自己的委托作为他调用的异步委托完成的通知,让他自己立即回到工作,但是仍可以在别人给他的工作打分后得到通知:

宇宙中的幸福

彼得、他的老板和宇宙最终都满足了。彼得的老板和宇宙可以收到他们感兴趣的事件通知,减少了实现的负担和非必需的往返“差旅费”。彼得可以通知他们,而不管他们要花多长时间来从目的方法中返回,同时又可以异步地得到他的结果。彼得知道,这并不*十分*简单,因为当他异步激发事件时,方法要在另外一个线程中执行,彼得的目的方法完成的通知也是一样的道理。但是,迈克和彼得是好朋友,他很熟悉线程的事情,可以在这个领域提供指导。

他们永远幸福地生活下去……<完>

略懂 HTML 的朋友都知道,如果想让一个链接在新窗口中打开,通常的做法是利用 target=”_blank” 来设定 a 标签。例如:

  1. <a href=http://jennal.cn target=_blank>Jennal.cn</a>

这种做法确实比较方便,但在 XHTML 1.0 Strict 中去掉了 target 属性,也就是说我们不能再利用 target 属性来控制链接的行为。虽然当今流行的浏览器在 XHTML 1.0 Strict 甚至 XHTML 1.1 下扔能正确执行 target=”_blank”,但这样的代码毕竟是不规范的,不推荐使用。

很自然,我们会想到用 Javascript 来解决这个问题,我通常是使用下面的方法:

  1. <a href=http://jennal.cn onclick=window.open(this.href);return false;>Jennal.cn</a>

这样虽然可以满足要求,但是当链接很多的时候,代码就显得有些臃肿了。为了简化代码,我们应该用 DOM Event / DHTML 的方法来解决这个问题。今天我恰好在做一个网页,需要使用 XHTML 1.0 Strict,准备自己写一个这样的 Javascript。不过幸好我养成了万事先 Google 的坏习惯,还真让我找到了一个很完善的 Javascript 弹窗代码,这段代码不仅写的漂亮,通用性强,而且还考虑到了当今流行的浏览器按下组合键点击链接的情况,已经非常完善了。代码源头在这里,作者提供了源码下载和一个演示

这段代码的通用性非常强,作者原文中举例写的也很详细,其实最简单的用法就是为需要开新窗的链接添加 rel=”external” 属性,当然,你也可以自己定制根据 class 或其它什么属性来判断。

  1. <a href=http://jennal.cn rel=external>Jennal.cn</a>

当然,在网页设计中,弹出新窗口在多数情况下应该尽量避免,只在可以提高用户体验的情况下才需要使用。此外,由于有些 Pop Window Blocker 会拦截 Javascript 弹出窗口,我们可以修改这段代码,通过判断窗口是否成功建立来给出关闭弹窗过滤的提示,相信可以使用户体验提升不少。

转自:http://blog.istef.info/2007/05/17/open-a-new-window-when-click-a-link-under-xhtml-10-strict/

php下载文件的函数

转自:http://www.ruofeel.cn/329.html

Javascript 刷新页面的几种方法

1    history.go(0)
2    location.reload()
3    location=location
4    location.assign(location)
5    document.execCommand(‘Refresh’)
6    window.navigate(location)
7    location.replace(location)
8    document.URL=location.href

搞定一个很纠结的json问题,记录一下

今天被json编码中文搞死了。。。
json_encode中文的时候,会把每个中文字符encode成“\uxxxx”
而存进数据库的时候,“\”被屏蔽了,直接变成”uxxxx”
郁闷,我还以为是json_decode的问题。。。在网上查了一个下午资料都没解决
直到发现网上的文章都说json_encode是把中文encode成“\uxxxx”,我才顿悟。。。
经过一番实验,才发现问题出在存储到数据库的环节。。。
特此纪念一下

至于解决办法,当然是让”\”保留啦,把”\” replace成”\\”就可以啦~

还有一个问题,差点忘了,就是json_decode以后返回的不是array,而是stdclass,有一个很郁闷的问题,如果hash带下划线,如json[‘xx_yy’]会出现很奇怪的问题,页面什么都不显示,也不报错,差点晕死。有一个办法解决,就是先foreach一下,把带下划线的存到一个array里面,或者直接整个转存成array。

//感谢软工的回复
由于已经是2年前写的博客,也没有写实际场景,我已经忘记json_decode是在什么场景下出现的问题。
如果我没有记错的话,当时json_decode还没有第二个参数。

PHP get remote ip address

Discuz!源代码分析[模板使用include template(discuz)]:./include/template.func.php

本帖不仅仅是分析文件,还把Discuz中模板解析这一原理分析了一下。转自www.discuz.net 作者:郭鑫

我记得我刚开始学PHP的时候,对模板解析实在是觉得很奇怪,不知道这个原理怎么实现的,后来看书看多了也明白有一个著名的Smarty在那,曾经也用过一段,不过感觉不是很好,就开始分析Discuz的模板技术是怎么实现的了,然后我把这个模板解析的代码分离出来了,觉得很好用,用了一段时间, Discuz的模板解析是用正则表达式替换一些模板中的规定的语言标记,然后呢,写到forumdata/templates中,再用include引用到index, forumdisplay等等中,和smarty的原理基本上相同,只是功能没有smarty那么多,smarty内建了一个cache来着…连个 User Guide都几百页…
  呵呵,不过现在基本上两个都没用过,正则表达式好是好用,不过正则的效率不是很高,以前看PHP技术文档的时候说能不用正则就尽量不要用,那东西烦着,现在做什么项目基本上用的是框架,MVC的模式,View中的代码一般不用模板解析出来,混杂php代码在里面,也觉得不错,OOP的开发效率比较高,很多地方重用代码是很开心的~!

  Discuz的模板解析要分析出来只要用到两个文件:./include/global.func.php和. /include/template.func.php,global只要一个函数就够了,template要全部的文件下面我就分开讲一下,会比较详细,大家耐心看:

Section One–./include/global.func.php—->template function

这个函数一共有三个传入参数:

$file 表示模板名
$templateid 表示模板id
$tpldir 表示模板目录

这个是把$tplrefresh作为一个全局变量,tplrefresh表示是不是刷新模板

$tpldir和$templateid赋值,如果没有传进来就用常量TPLDIR和TEMPLATEID给它们值

这里是把$tplfile(表示的是模板文件)和$objfile(表示的是要编译成的文件)赋值

防止TEMPLATEID不等于1且$templateid不等于1,而且模板文件不存在导致空白问题。
这里也可以算一个迭代,也可以不算,就是把1作为第二个参数再调用函数本身。

很巧妙的一段,Discuz的模板缓存就体现在这里,如果你没打开模板刷新的话(config.inc.php->$tplrefresh=0),这里就直接返回一个$objfile了,而这个文件是你第一次建论坛的时候就写入的,如果你不改模板的话,关了是能提高相当一部分效率的!反之,如果你打开了模板刷新的话就接着判断是不是模板文件的建立时间大于 forumdata/templates下的文件,是的话就引用./include/template.func.php写入模板文件到 forumdata/templates中,否则的话还是直接返回一个已经编译好的模板文件。
关于template.func.php文件中函数的分析在下面:

如何快速的呈现我们的网页

一、我们需达解决的麻烦

  • 减少HTTP请求数. 减少HTTP请求数有什么好处
    • 降低服务器跟客户端的建立和消除HTTP请求和响应Header的开销
    • 减少服务器为HTTP连接的进程和线程的开销,如果可能,还会包括GZIP压缩的CPU开销.
  • 减小被请求文件大小, 减少请求数据占用的网络带宽.
  • 让用户更快的看到想要的结果.
  • 提高客户端渲染速度.
  • 让浏览器同时能请求更多的数据.
  • 提高服务器相应速度.
  • 通过版本化控制客户端Cache.

二、如何解决我们的麻烦

A.如何减少HTTP请求数

  1. 合并JS文件跟CSS文件。
  2. 合并框架图片以及相对变动较少的图片成一张,通过CSS背景切割来完成渲染,比如:加速图片显示
  3. 合理使用本地Cache来缓存JS/CSS/IMAGE。
  4. 合理使用UserData缓存JS文件,对于FF用户可以单独请求服务器,这样能解决80%用户的问题.代码可以蓉儿(meizz)的js framework1(标注1)。
  5. 把JS跟CSS合并成一个文件

B.减小被请求文件大小,减少请求数据占用的网络带宽

  1. 压缩JS体积:删除JS中空白换行,注释,混淆把长变量换成短变量;
  2. 压缩CSS体积:删除CSS注释、写法尽量用简写;
  3. 使用(X)HTML+CSS方式搭建网站结构,提高CSS重用性,来减少(X)HTML文件大小;
  4. 使用服务器端GZIP压缩JS/ CSS文件,缩小传输文件大小。附注:Apache1跟Apache2的GZIP的效率跟方式不一样的,根据需要自行选择。

    嗷嗷补充说明:压缩、合并JS和CSS都由程序处理。而不是自己手动去缩删,不然不利于后期维护。

C.让用户更快的看到想要的结果

用户对于一个站点的白页的忍受时间根据统计是8-12秒。白页的产生可能由于各种原因引起,我们能做的就是怎么让用户能变的稍微能等待更久。

  1. 方案1:多做一个引导页,让用户体会其中的变化
    案例:mail.aol.com中的loading引导页
  2. 方案2:优先载入页面结构以及结构图片,后一步载入当前页面数据,再后一步载入Iframe,Flash等数据.让用户尽早的看到被打开页面的希望.

D.提高客户端渲染速度

这个问题就比较泛泛了,影响客户端的渲染速度有多方面的,主要目的都是提高程序方面的效率.

  1. 对于大索引的结构,尽可能的少用索引访问,能用访问兄弟节点的方式尽可能用访问兄弟节点的方式.
  2. 字符串拼接尽可能用数组方式
  3. 大规模添加节点数据,请不要使用appendChild方式,尽量使用类似innerHTML的insertAdjacentHTML方式,FF下需修正(标注1)

E.让浏览器同时能请求更多的数据.

浏览器默认只是支持单域名同时有两个HTTP请求,使用多域名将能把请求数提高,在网络条件优良的情况下,能更快的下载数据,呈现结果.

F.提高服务器相应速度

对于需快速响应的文件,把其放入快速响应的服务器,应该是不错的方案,优化方案请系统储备组提供.

G.通过版本化控制客户端Cache

通常js/css这类文件改动比较频繁,但是为了加载速度变快,我们有可能需要设定这类文件的过期时间为几天后,这样我们碰到的问题就是,如何及时更新这些在cache的文件?
通过一个简单的配置,通过修改JS的版本来及时告诉浏览器,这些文件必须重新请求了,不要继续使用浏览器cache中的数据. 方案有好几个:

  1. 手动改这些js的文件名
  2. 手动改这些js的路径
  3. 通过URL Rewrite方式来改重定位js路径
  4. 通过一个在高响应服务器上的一个js配置告知页面,这个页面该链接哪些JS文件
  5. 大版本不变,小版本不断追加,等一定时间后,统一更新,高效利用cache

标注

  1. meizz的js framework还没出正式版,有兴趣在CSDN的页面翻一下
  2. Firefox修正方式

转载于:http://www.blueidea.com/tech/site/2007/4822.asp

[转]关于大家问的uc开发手册不能同步登陆问题

最近在做一个整合 UCenter 的项目,下载了一份 uc开发手册,测试结果是这样的:
通过uch 登陆 可以同步登陆到论坛,但是不能登陆到 ucexample_1.php 和 2 这个开发手册自带的例子中。
但是通过ucexample_1.php 和 2 的例子登陆是可以登陆到 uch 和 论坛的
所有都是在配置正确的前提下进行,在 uc管理中的 应用管理 通信是要成功的。

那么问题是如何出现的呢?
看一下 api/uc.php
99-110行

  1. //同步登录 API 接口
  2. include ‘./include/db_mysql.class.php';
  3. $db = new dbstuff;
  4. $db->connect($dbhost, $dbuser, $dbpw, $dbname, $pconnect);
  5. unset($dbhost, $dbuser, $dbpw, $dbname, $pconnect);
  6. $uid = intval($get[‘uid’]);
  7. $query = $db->query(“SELECT uid, username FROM {$tablepre}members WHERE uid=’$uid'”);
  8. if($member = $db->fetch_array($query)) {
  9. header(‘P3P: CP=”CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR”‘);
  10. dsetcookie(‘Example_auth’, authcode($member[‘uid’].”\t”.$member[‘username’], ‘ENCODE’), 86400 * 365);
  11. }

复制代码

你会发现是一个读取数据库的操作,读取到才能设置咱们自己应用的 cookies 的
那么样例中似乎说的是要连接到自己的数据库中,可想如果咱们自己的数据库没有会员数据那么就登陆不成功了,所以解决办法就是读取uc自己的数据库!
在 app 的 config.inc.php 中
21-28行,不要看提示说是设置自己的,咱们直接设置 uc 的数据库

  1. //ucexample_2.php 用到的应用程序数据库连接参数
  2. $dbhost = ‘localhost';                        // 数据库服务器
  3. $dbuser = ‘root';                        // 数据库用户
  4. $dbpw = ”;                                // 数据库密码
  5. $dbname = ‘uc';                        // 数据库名
  6. $pconnect = 0;                                // 数据库持久连接 0=关闭, 1=打开
  7. $tablepre = ‘uc_';                   // 表名前缀, 同一数据库安装多个论坛请修改此处
  8. $dbcharset = ‘gbk';                        // MySQL 字符集, 可选 ‘gbk’, ‘big5′, ‘utf8′, ‘latin1′, 留空为按照论坛字符集设定

然后你在测试一下,通过论坛 uch登陆 也可以直接同步登陆到 示例的应用中了!

转自:http://www.discuz.net/viewthread.php?tid=1043330&extra=page%3D1&frombbs=1