[资源].NET 程序员必备工具下载

mikel阅读(714)

1、Snippet Compiler

Snippet Compiler 是一个基于 Windows 的小型应用程序,你可以通过它来编写、编译和运行代码。如果你具有较小的代码段,并且你不想创建完整的 Visual Studio .NET 项目(以及该项目附带的所有文件),则该工具会很有用。 

下载地址:

For .NET 3.5:
Snippet Compiler Live 2008 Ultimate Edition for Developers (Alpha)

For .NET 2.0 and older:
2.0.8.3 for .NET 2.0 | 2.0.7.1 for .NET 1.1 | Changes | Version 1 | Add-Ins

 

2、Microsoft Source Analysis for C#

Microsoft Source Analysis for C#是微软内部代码检查工具。能够帮助项目团队执行一系列常用的源代码格式规范,这些规范是关于如何开发布局规整、易读、易维护并且文档良好的优雅代码的。

这个工具包含了一些最佳实践规则,和 Visual Studio 2005、2008 中默认的代码格式化规则是一致的。

  • (布局)Layout of elements, statements, expressions, and query clauses
  • (括号)Placement of curly brackets, parenthesis, square brackets, etc
  • (空格)Spacing around keywords and operator symbols
  • (行距)Line spacing
  • (参数)Placement of method parameters within method declarations or method calls
  • (元素排列)Standard ordering of elements within a class
  • (注释格式)Formatting of documentation within element headers and file headers
  • (元素、字段、变量的命名)Naming of elements, fields and variables
  • (内置类型的使用)Use of the built-in types
  • (访问修饰符)Use of access modifiers
  • (文件内容)Allowed contents of files
  • (调试文本)Debugging text

HelloCTO.com进入下载

 

3、GhostDoc

GhostDoc 是Visual Studio的一个免费插件,可以帮助开发者生成比较完整规范的XML格式代码注释,如果你的代码遵循微软类库开发人员设计规范 ,由它自动产生的注释就已经完全可以很好地表达开发者创建的方法或者属性的意图,无需手工再进行修改。有了这些标准的XML注释,我们可以使用微软的文档 工具Sandcastle生成专业级别的帮助文档。如我们有这样一段代码:

HelloCTO点击下载:GhostDoc2.1.3 for Visual Studio2005 

  • WinXP, Win2k3, Vista
  • For C#, support for VB.Net is "experimental"
  • HelloCTO点击下载:GhostDoc Version 2.1.3 for Visual Studio 2008

  • WinXP, Win2k3, Vista
  • For C#, support for VB.Net is "experimental"
  • HelloCTO点击下载:GhostDoc Version 1.3.0 for Visual Studio .NET 2003

  • WinXP, Win2k3
  • Support for C# only
  •  

    4、Sandcastle

    Sandcastle 是微软发布的一个帮助文档生成工具,它通过反射程序集中的源代码和添加代码到中的XML注释来创建专业级别的帮助文档。Sandcastle于2006年 推出,它的面世也使得曾经列入.NET开发必备十大工具之一的文档生成工具NDoc的作者Kevin Downs在2006年7月宣告不再投入 NDoc Open Source Project的开发。生成的文档效果如下图所示:

    HelloCTO.com进入下载页面

     

    5、Reflector for .NET

    相 信大名鼎鼎的Reflector for .NET大家都已经用过了,几年前它已经位于.NET开发必备十大工具榜,现在自然也不能例外。它是一个类浏览 器和反编译器,可以分析程序集并向你展示它的所有秘密。使用Reflector for .NET可以浏览程序集的类和方法,可以分析由这些类和方法生成 的 Microsoft 中间语言 (MSIL),并且可以反编译这些类和方法并查看 C# 或 Visual Basic.NET 中的等价类和方法。 经过多年的发展,Reflector for .NET已经发展到了5.1版本,并且提供了相当丰富的插件,利用这些插件我们可以浏览 Silverlight程序结构、浏览WPF资源文件、与TestDriven.net集成等。如下图所示:

    HelloCTO.com点击进入下载页面

     

    6、The Regulator

    The Regulator 能够使生成和测试正则表达式变得很容易,它允许你输入一个正则表达式以及一些针对其运行该表达式的输入。这样,在应用程序中实现该正则表达式之前,你便可 以了解它将产生什么效果以及它将返回哪些种类的匹配项。另外它还提供了正则表达式库管理功能,在线更新正则表达式库,可以在RegexLib.com上搜 索需要的正则表达式,如下图所示:

    HelloCTO.com点击进入下载页面

     

    7、LINQPad

     随着在.NET Framework 3.5 中对于LINQ的支持,越来越多的开发者在开发中使用了LINQ to SQL,但是编写LINQ to SQL查询似乎又成了一件很麻烦的事情,好在我 们还有LINQPad这个工具,用来编写LINQ查询,不仅仅是LINQ to SQL,同时它也支持LINQ to XML、LINQ to Objects,另外LINQPad是完全免费的且无需安装,只要下载它的可执行文件就可以了。


    8、FxCop

    .NET 框架非常强大,这意味着存在创建优秀应用程序的极大可能,但是也同样存在创建劣质程序的可能。FxCop 是有助于创建更好的应用程序的工具之一,它所采用的方法是:使您能够分析程序集,并使用一些不同的规则来检查它是否符合这些规则。FxCop 随附了由 Microsoft 创建的固定数量的规则,但您也可以创建并包括您自己的规则。例如,如果您决定所有的类都应该具有一个不带任何参数的默认构造函数,则可以编写一条规则,以 确保程序集的每个类上都具有一个构造函数。这样,无论是谁编写该代码,您都将获得一定程度的一致性。如果您需要有关创建自定义规则的详细信息,请参阅 John Robbins 的有关该主题的 Bugslayer 专栏文章(MSDN ® Magazine 2004 年 6 月刊)。

    那么,让我们观察一下实际运行的 FxCop,并且看一下它在我一直在处理的 NUnitExample 程序集中找到哪些错误。当您打开 FxCop 时,您首先需要创建一个 FxCop 项目,然后向其添加您要测试的程序集。在将该程序集添加到项目以后,就可以按 Analyze,FxCop 将分析该程序集。图 6 中显示了在该程序集中找到的错误和警告。

    FxCop 在我的程序集中找到了几个问题。您可以双击某个错误以查看详细信息,包括规则说明以及在哪里可以找到更多信息。(您可以做的一件有趣的事情是在框架程序集上运行 FxCop 并查看发生了什么事情。)

    FxCop 可以帮助您创建更好的、更一致的代码,但它无法补偿低劣的应用程序设计或非常简单拙劣的编程。FxCop 也不能替代对等代码检查,但是因为它可以在进行代码检查之前捕获大量错误,所以您可以花费更多时间来解决严重的问题,而不必担心命名约定。FxCop 由 Microsoft 开发,并且可以从 http://www.gotdotnet.com/team/fxcop 下载。

     

    [管理]焦油坑---走出软件作坊:三五个人十来条枪 如何成为开发正规军(十八)

    mikel阅读(673)

          我有一个以前的同事。过去他总认为能成事的人什么时候都能成事,不能成事的人你再扶他也成不了事。所以他带领人的方法一般是他以身作则,你如果有悟性,你就照着他做,如果你看不出来,那么你就自己一个人玩着去,能玩成什么样玩成什么样。

          我主张的是:普通人通过使用一定的方法和规则,做事情虽然无法做到优秀,但也至少能保持一定水准,不会把事情做烂。如果任由普通人自己去想自己去做,这要 管理者何用?作为管理软件开发公司,其管理思想,竞争不过管理咨询公司,其技术实力,又没有技术门槛,属于那种规模化生产实施服务的类型。所以,管理软件 开发公司要想成长,必须走规模化路线。而规模化路线就需要依靠大量的普通人才,而非个别的英雄。英雄是很难找到大量人才的,而且优秀的人才其成本也高,更 约束的无法规模扩张。这和规模化路线有悖。

         所以,他带出来的兵都是单兵作战能力很高,都属于那种能救火队员型,有问题冲上去嘁哩喀喳就搞定。领导是很喜欢这样的人才的,因为这样的人是多面手,是特 种战士,把一个人随便往哪一扔都能把项目完成的很好,很省成本。但是这样的人才有个特点,没有一年半载,这样的人培养不出来。而且这样的人往往都游兵散勇 似的,一遇到必须合作的事情就变扭,老觉得其他人办事都不放心,都觉得别人做的没他预想的那么好,还不如自己一个人都包办了快速且省事。

          而我带出来的兵都是团队作战型,每次做事,都需要好几个各自发展专业的人配合,一个人还搞不定。就好像开发的时候用开源的框架,本来只想使用A框架,没想 到A框架使用了B框架,B框架使用了C框架,最后软件没多大,倒是框架很大。虽然我都是极力推行四套马车4人一个小组,而且可以看项目进展安排不断调度组 合,但终究不如一个特种战士那样自由。但有一个好处就是做事专业,发挥稳定,培养成长快,好招聘好留人团队稳定,薪资成本也低。

          隔了这么多年,我的电话也换了,他的电话我也没记住。我们就这样断了联系。

          突然,上个星期五,他给我发了封邮件。说他偶尔看到了我的博客,写的不错(不知道是不是真的不错,反正他以前一直反对我的这种思路),希望我能写些关于需求管理的文章。

          我赶快根据他邮件中留给我的联系方式联系到了他。

          我问他:你怎么找到我的博客的?

          他说:这几年越来越不好做。客户对开发对实施对服务的质量要求越来越高,一个人去现场边修改边实施,客户觉得付那么多钱不合算,怎么着也得派一个团队来实 施。但是,团队实施没有人手啊。培养一个人一年都上不了手,对于我们来说团队实施就不合算了。但客户就要团队实施,不团队实施就无法接单。所以,我现在也 在找一些如何团队开发实施的文章,无意就找到了你的博客。

          我们现在也是文档化管理。从需求调研到需求确认到需求设计到需求开发,每一个环节我们都是和客户文档确认,大家都觉得没有问题了双方看法一致才开发。一开 始使用就发现需要修改的东西很多,而不修改又导致客户无法使用下去,最后不断修改,导致实施周期长,结果还跟过去一样,质量也没提高,周期也没有缩短。所 以,比较迷茫,是不是哪里做的有问题?你一直挺注重过程管理,看你写了那么多文章,肯定这么多年你一直在研究这方面,所以我估计你有一些好的方法。

          我说:我这些天写博客,接到不少网友的评论,他们也强烈希望我能写一篇关于需求管理的文章。我过去也有一些只言片语的积累,所以这次我就准备写一篇以了大家心愿。

          当我开始动笔写这篇博客的时候,我脑海里直接的就是《人月神话》中最著名的一段话(不好意思,其实我没有看过人月神话,不知道作者提供了什么解决方法解决需求难题):

          人类史前史中,没有别的场景比巨兽在焦油坑中垂死挣扎的场面更令人震撼。上帝见证着恐龙、猛犸象、剑齿虎在焦油中挣扎。它们挣扎得越猛烈,焦油纠缠得越紧,没有任何猛兽足够强壮或具有足够的技巧去挣脱束缚,到最后它们都沉到了坑底。

          这段话描写的栩栩如生,和我们日常遇到的需求困境如出一辙。

          中国人的需求很特别,好像事情都特别赶人都特别忙似的,都寥寥数语就以为他的需求已经说清楚而且你也肯定明白了,到底能不能实现,实现后能不能可操作可执行,都是匆匆一个见面一个电话几句MSN几句MAIL然后就等着软件开发出来用。

          我看到日本人花费一年的时间反复和客户讨论需求,深入到生产一线天天蹲点,还派人拿专业的测量工具来记录,如拿秒表记录操作的时间,拿摄相机拍摄操作流 程,有大量的过程检测指标需要15分钟确认一次,很是认真,然后才设计解决问题的软件功能。对于每个操作的软件界面也是反复和客户确认,如何更容易理解更 方便操作。

         我见到许多国内项目经理调研没个方法,东一榔头西一棒槌,需求调研像是开座谈会,一屋子人,有干系的人都请来开会。有最终操作用户,有部门管理者,有大老 板,有二老板,有计算机室,好几个部门。每个人站的角度,层次都不同,关注的问题重点也不同,眼光长远也不同,有人悲观有人乐观,有人不懂装懂,有人不懂 瞎嚷嚷,有的部门影响力大气粗的不行,有的部门比较势力小唯唯诺诺,有的部门不愿意多干就推来推去反正不是他部门的事情,到底是哪个部门的事情需要大领导 来定,但可惜大领导没来,有的部门怕自己那点内部发小财被破坏了就故意找各种各样的困难还说的头头是道,于是一帮人叽叽喳喳,没个结论。有时候开会开多 了,实在说不过去了,必须要有一个结论,于是每个人的意见都上了需求本,回来一整理,没法弄。

         我曾经参与过一个项目就遇到了这样一个情形,最后拖的时间太长,项目主导方认为没什么利益可赚,而客户冲突利益太多,就放弃这个项目了。

         “表面上看起来好像没有任何一个单独的问题会导致困难,每个问题都能获得解决,但是当他们相互纠缠和积累在一起的时候,团队的行动就会变得越来越慢。”对于问题的我们很难看到本质,不过,如果我们想解决问题,就必须试图先去了解问题。

         这是《人月神话》中的一段话,我从网上找到的,估计那个项目经理很遗憾没有看到这句话。

          风水轮流转呀。真不小心,新一轮领导换届,新领导上台。这个项目又被作为领导新政提了出来。(注意,不是政府换届,而是企业领导换届。我从来没有做过政府的单子)

          这回,项目主导方变成了我们。我成了项目经理。但是,除了这位新领导,过去的那帮人还是那帮人,我仍然要解决这帮人。(我的一位助手笑称这帮人是成事不足 败事有余。上一次我是挂名,他是真正参加了上一次的项目每一次开会。这次,我找他做助手,希望他的上一次经验能给我提供帮助)

          我这次没有像我的助手上次项目一样,让计算机室帮忙到业务部门要这信息那表格。

          我首先向计算机室要了一份全企业的部门组织结构图。我先看看这个盘子到底多大。我曾经刚出道的时候就遇到一次滑铁卢,半路地杀出来一个部门领导竟然严重影响了项目走向。

          这次,我把全体部门都纳入思考范围内,了解我这个项目和各个部门的关系。最后我按项目关系紧密程度把客户各个部门排了一张表,每个部门的负责人的名字,联 系电话我都要到,每个负责人的年龄,每个负责人的性格,我通过晚上请计算机室没有结婚的小伙吃羊肉串了解了个一清二楚,谁说话算话,谁比较和事佬,谁比较 见风倒,谁和谁不对付。想问问他们大老板是怎么看这个项目的,想达到什么目标,他说他也不清楚。

          我先去亲自找最容易配合我的那个部门(我并没有采用聚众开座谈会的形式,而是单个击破法)。但他不是和我这个项目关联最紧密的部门。但他最容易突破。

         他和我发了一下午的闷气,有对企业现状的灰心与不满,有对理想做法的想象,希望我能在这次项目中把他的想法全部实现了。

    不过这次聊天我也受益匪浅,对这个企业的各种来龙去脉了解了许多,使我在以后的小心翼翼项目推进中避免了很多人为的障碍。

    但这不是我这次找他谈的真正目的。他絮叨了一下午,我临走时才说出了我的目的:我需要把他这个部门的报表和单据收集回去。

    他很配合,把他的得力干将叫了过来准备安排,我说别了,我跟着他去自己收集,这样我对您的需求也理解的更深更直观一些。

    于是,我跟着他的得力干将,一位36-37岁的中年女士一一到每个重要的人的桌边,我和每个人都讲明了我的来意,他们将他们手头的报表和单据全都拿 给了我。有EXCEL的,有WORD的,有每月PPT述职报告,有纸张的,有电脑软件上的报表都打印出来,有电脑软件上的数据输入,我就帮他们COPY屏 幕打印放到我的U盘上。

         我一个人一个人的边收集边问,通过他们给我的表格,我就大致知道了他们的工作岗位内容。

         然后,我问:哪些表格是你最常用的。

         于是,那个人就帮我挑出了好几张。

          然后,我依次把最常用的,次常用的,偶尔用的报表都分了类。

          我又提出了问题:哪些报表影响你的考核和奖金工资福利之类?

          他又帮我挑出来一些。

          我又对着他挑出来的影响他的考核的报表,拿起每一张问他:在这张报表中,你最关注哪几个指标?

          他一一指出来。我顺着他的指,边和他交流这些指标的关联关系。

          然后我拿着这些指标问他,这些指标是怎么的数据是怎么得来的。

          他就帮我从这一堆的电子的、纸张的单据中找了出来,并且解释怎么输入的。

          然后我对着每一个单据都问他这个单据的使用频率,是每天、每周、每月、每季还是每半年、每年。是每天(周、月、季、半年、年)的期初做、期末做、还是平时做?哪个频率高?高到什么程度?

    这样,我就明白了每个人主要真正做哪些事,怎么做,最后怎么考核,哪些事最重要,哪些事每天做,哪些事频率最高。

          常用的功能,重要的功能,性能压力大的功能,稳定性要求高的功能、数据精确要求高功能,易操作性要求高的的功能,就是从这些提问回答中自然浮现出来的。

         我的那个助手用笔在笔记本上不断记录,手累的最后回来都说手写的都抽筋,告诉我下次不要这么快,让他好记录全一些。还给我看,为了记得快,字都写的有些现在不认识了,还得靠回忆,整理起来特费劲。我说,行,行,我一定注意。

          我们回到宾馆后,先制作了一份草稿,粗略的列出来这个部门的组织结构、人员岗位角色说明、业务流程图、考核报表。第二天,然后针对这次项目,把这次项目相关的详细描述出来,并且把核心业务流程和非核心业务流程分开。

          第三天上午,我们又去了那个部门,针对每个报表间的钩稽关系,每张单据录入的每一项录入要求、默认值、必填项、唯一约束、录入校验、单据状态、可选值都做了详细调研。

          在交谈中,我们又发现了一些流程,这些流程都是些特殊处理流程。我们也发现了一些异常的操作,是发生特殊业务时候的土处理,我们都如实记录了下来。有时 候,你专门问他异常流程的时候,他反而回答不出来。大部分人没有系统性思维,都是以事论事,讲到哪里想到哪里。所以发现异常流程,发现新流程,全靠调研人 自己细心发现和甄别。可能,他无意的一句话,你直追着下去就会发现他日常处理的空白和漏洞和矛盾的地方。

          第三天下午,我们继续工作,单个人访谈,把每个人工作中认为最想解决的问题都提出来,但只能说5个,能想到哪些就说哪些,我们一一记录。

          第四天,我们把我们过去画好的组织结构、人员岗位角色说明、业务流程图,经过昨天的调研,又修改补充了一些,在整理的时候,我们用红圈标好了业务处理漏洞 和矛盾的地方,并且对这些地方都提出了改进建议。把他们每个人认为最想解决的问题都考虑进流程和业务单据报表中,建议增加什么流程、建议增加什么单据、建 议增加什么报表,谁来做,怎么做,谁来监督,怎么考核。

          一份优化好的流程展现出来了。

          第五天,我们又去了客户那里。这次,我们组织了部门座谈会。我们给他们整个部门都讲解了我们梳理过的流程现状,给他们说明漏洞和矛盾,给他们说明我们提出的方案。

          座谈会非常顺利,全在我们的意料掌控之中。他们非常惊讶我们能在短期内画出这么专业的流程图,其理解透彻度比他们自己还要清楚。而且对他们问题的把握准 确,对他们问题的解决思路之巧妙,都不禁赞叹我们。每个人的疑问和建议都融入了我们的流程改进思考之中。客户部门给与了我们很高的评价。

          接下来,我并没有把这种方法扩展到其他客户业务部门的调研。而是我把这份调查报告又给了他们大老板演示了一次。他们的大老板从来没见过这样专业的调研,赶 快召集各部门头头都来开会,乐的喜笑颜开, 大赞这钱花的值,他们只想到上套软件,没想到上软件讲究这么大,他们自己都没有如此明晰专业的流程图。他们的大老板赶快让我给他也COPY一份,如获珍 宝。

          有了大老板的肯定,我做一个部门的调研,就给他们的大老板发一个报告邮件。邮件抄送给调研的业务部门负责人。

          我所有的调研一帆风顺,各个部门配合极好。上一次项目的扯皮推搡都不见了。

          我的助手说:你这个人有点邪门。

          我一笑。

          后续记:

          我写完这篇博文后,引起了网友这样的评论:其实这些事情都是管理咨询公司做,你现在做了这些,其实是增加了你的工作成本。

          并没有想过这件事该管理咨询公司做,那件事情该软件公司做。我只想解决我的问题,我的方法也是由此而来的。

          如果我对客户说:“你们还不规范,现在不能上软件,需要你们先去找管理咨询公司来梳理流程”。我不知道我们的公司会不会活到现在。

          解决问题,这是你自己面临的问题,你不去自己想办法,没有人会给你解决这个问题。能救你自己的只能是你自己。

    [C#]表达式树

    mikel阅读(830)

    已经有很多很多人聊过这个话题,今天我在这里重复也不会探讨出什么新东西,只是把自己的理解描述出来,更是为了整个系列文章的完整性。

    当你听说Linq给你的承诺时,你怎么想的?Wow,我们可以以统一的方式操作各种各样的数据了。这就是我当时的想法。虽然人们在现实中总是喜欢差异,认为差异才能产生美,如果一切的一切都是一样的,这个世界将无比的单调,可是作为程序员的我们却对标准趋之若鹜,对差异嫉恶如仇。看同桌的你是不是正在为了OracleSQL Server两种数据库编写两套数据访问的类?

    表达式树概念

    Linq的承诺貌似Java那个梦想一样:Write Once,Run AnywhereJava是怎么做到的?Sun等公司为我们在各种平台架构上实现了各自的虚拟机,Java的编译分为两个阶段,第一阶段将Java代码编译为字节码,在这个阶段不管在什么平台上,只要Java源代码一样生成的字节码是一致的,第二个阶段,也就是运行阶段,虚拟机会根据平台的不同生成不同的代码。就是通过将编译器分为前端和后端来实现这个梦想。

    实际上LINQ也是这么做的,对各种数据的操作无非“增删查改”,但是具体做的时候关系数据库需要使用SQL来操作,而XML需要XPath来操作。我们如何将“增删查改”的语法做到一致,让我们用起来好像操作的数据只有一种?

    答案是使用表达式树

    表达式树仅仅是将表达式(这里特指Lambda表达式)用树状的数据结构来表示。相当于Java的字节码,至于如何去解析这个树的结构那就看你自己了,如何去解释这个表达式树。

    看下面这个Lambda表达式:

    username => username == “yuyi”

    我们主要看表达式的主体:username == “yuyi”,如果我们是要对数据库进行操作,这将翻译为字段username中所有值为”yuyi”的行,如果操作的是XML那也许是查询名称为username,值为”yuyi”attribute。表达式树承载的只是这样一个结构:

     

    如何解释它这是你的事。

    C#Expression<Function<string,bool>> IsTrue = username=>username==”yuyi”,就表示一个表达式树,这个语句在编译后就组成为一个树状的结构。

    在编译原理中,我们知道编译器的前两个阶段主要做的是:词法分析、语法分析。在词法分析中编译器会从代码文件中读入一个个的字符,然后识别出其中的关键字、标识符、运算符、常量、字符串等。

    比如上面的表达式就会识别出:

    Username->标识符

    ==->运算符

    “yuyi”->字符串

    这些东西就叫做符号

    然后以这些符号作为输入进行语法分析,语法分析会将这些符号组合成一个树,这个树我们称之为抽象语法树(AST),表达式树也是一种简单的AST

    (在VS2008带的例子中有个DynamicQuery的例子,这里有一个Dynamic.cs文件,这里就自己做表达式的解析,只不过解析的是用字符串形式的表达式,通过这个代码你可以看看表达式的解析过程,这里有一个ExpressionParser类,它就是负责表达式的词法解析的,该类里有一个Token的机构,这就是上面所说的符号,TokenId表示符号的类型

    <"Samples"1033"CSharpSamples"LinqSamples"DynamicQuery>

    对于Lambda表达式,有两种编译方式,常规的:

    Func<string,bool> IsTrue = username => username == “yuyi”;

    这个时候编译器会将其编译为匿名方法,关于匿名方法的相关介绍可以参看我这篇文章

    编译成表达式树:

    Expression<Func<string,bool>> IsTrue = username => username == “yuyi”;

    这么细微的差别,C#这次却不真的编译这条语句,而是将其进行词法、语法分析,得到的是一个数据结构。

    我们注意到表达式树还有一个Compile实例方法,它可以将表达式编译成匿名方法,也就是这个数据结构可以向匿名方法转变。

    想想Linq to SQL,实际上它不就是C#作为源语言,SQL作为目标语言的一个编译过程么。形成表达式树(抽象语法树)后,就是代码生成了,只不过这个代码生成有的时候是生成代码,比如Linq to SQL,生成的是SQL语句,有的时候是生成的方法调用,比如Linq to XML,生成的是对XML文档的操作。

    为什么一样的语句,有的时候是操作内存中的对象集合,有的时候是操作远程数据库?请查看我这篇文章

    关于表达式树更多细节内容,你可以查看TerryLee老大的这篇图文并茂的文章

    [FCKEditor]FCKeditor教程集合

    mikel阅读(819)

     

    http://lingoosoft.blog.ccidnet.com/blog/ccid/do_showone/tid_107320.html
    http://lingoosoft.blog.ccidnet.com/blog/ccid/do_showone/tid_107323.html
    以下内容为收集整理:==========================
    JavaScript调用方式:
    ------------------------------------
    <script type="text/JavaScript" src="FCKeditor/fckeditor.js"></scrīpt>
    <textarea name="content" cols="80" rows="4">
    </textarea>
    <script type="text/javascript">
    var oFCKeditor = new FCKeditor("content");
    oFCKeditor.BasePath = "FCKeditor/";
    oFCKeditor.Height = 400;
    oFCKeditor.ToolbarSet = "Default";
    oFCKeditor.ReplaceTextarea();
    </script>
    ------------------------------------
    如果想要使用从数据库读来的文本数据或者是后台来自文件的txt/html文本数据。
    只要在
    ------------------------------------
    <textarea name="content" cols="80" rows="4">
    </textarea>
    ------------------------------------
    中加入自己的显示内容的formbean对应字段即可
    ------------------------------------
    <textarea name="content" cols="80" rows="4">
        <c:out value="${contentData}" />
    </textarea>
    ------------------------------------
    这样内容就会被显示在FCKeditor编辑框中了,点击提交按钮以后就可以在后台的相应java action中得到content参数中的内容就是页面上FCKeditor中的内容数据了。可以在struts/jsf中使用。
    ====================================
    由于给FCKeditor瘦身,所以常会报缺少对象支持等错误,只要在FCKeditor/editor/lang中加上相应的js语言文件即可。如果加 载页面失败(FCKeditor未定义)还有一个可能就是引用FCKeditor/fckeditor.js文件路径不对!
    关于FCKeditor瘦身要点如下:
    1.将FCKeditor目录下及子目录下所有以“_”下划线开头的文件夹删除
    2.FCKeditor根目录下只保留fckconfig.js, fckeditor.js, fckstyles.xml, fcktemplates.xml,其余全部删除
    3.将editor/filemanager/upload目录下文件及文件夹清空
    4.将/editor/filemanager/browser/default/connectors/下的所有文件删除
    5.还可以将editor/skins目录下的皮肤文件删除,只留下default一套皮肤(如果你不需要换皮肤的话)
    6.还可以将editor/lang目录下文件删除,只保留en.js, fcklanguagemanager.js, zh-cn.js, zh.js文件
    7.如果你是使用javascrīpt来调用加载FCKeditor,那么就不需要在web.xml中配置fckeditor的tag文件。
    8.还有一个问题刚开始使用FCKeditor的人常会遇到就怎么控制它的toolbar的大小和元素排列,其实很简单。
    在fckconfig.js中用这样的标签[]来划分每行的元素的多少,这样就可以控制toolbar的长短和大小了,具体示例参看:fckconfig.js中的toolbarset["Default"]
    ====================================
    用fckconfig.js中的一些选项来控制toolbarset中控件的功能,实现功能裁剪:
    1):取消超链接中的浏览服务器和上传功能,方法如下:
    ------------------------------------
    FCKConfig.LinkBrowser = true;
    FCKConfig.LinkUpload = true;
    改为:
    FCKConfig.LinkBrowser = false;
    FCKConfig.LinkUpload = false;
    ------------------------------------
    2):取消图片链接中的浏览服务器和上传功能,方法如下:
    ------------------------------------
    FCKConfig.ImageUpload = true;
    FCKConfig.ImageBrowser = true;
    改为:
    FCKConfig.ImageUpload = false;
    FCKConfig.ImageBrowser = false;
    ------------------------------------
    3):Dlg Button中取消高级功能,方法如下:
    FCKConfig.LinkDlgHideAdvanced = false ;
    FCKConfig.ImageDlgHideAdvanced = false ;
    改为:
    FCKConfig.ImageDlgHideAdvanced = true ;
    FCKConfig.LinkDlgHideTarget = true ;
    ------------------------------------
    下一篇介绍FCKeditor的上传和浏览服务器功能,以及如何在里面实现动态
    超连接,转发到servlet经过filter以后去调用服务器的action
    如何实现对应用户浏览自己的图片的列表实现!
    ====================================
    FCKeditor集成java servlet可以实现文件的上传和服务器端列表读取功能FCKeditor自己提供了两个servlet来分别实现上传文件功能,和读取服务器端文件列表功能,这两个servlet分别为:
    com.fredck.FCKeditor.connector.ConnectorServlet(读取文件列表)
    com.fredck.FCKeditor.uploader.SimpleUploaderServlet(实现文件上传)
    1.浏览服务器端文件列表
    ------------------------------------
    web.xml文件中,比如:ConnectorServlet中的配置选项:
    <init-param>
        <param-name>baseDir</param-name>
        <param-value>/UserFiles/</param-value>
    </init-param>
    意思是在浏览服务器上的baseDir配置指定里面的所有文件及其目录结构列表。
    如果你的baseDir没有配置,Connector将会自动创建一个默认的文件夹
    UserFiles,对应的ConnectorServlet中init()方法中代码如下:
    ------------------------------------
    baseDir = getInitParameter("baseDir");
    if (baseDir == null)
        baseDir = "/UserFiles/";
    ------------------------------------
    还想说一下的是,FCKeditor的client调用server的servlet方法采用的是Ajax思想来实现。当你点击浏览服务器 (browser server)的时候就会触发一个异步的javascrīpt + xmlhttp的调用响应,后台的servlet会去完成你要请求的事件,然后数据以xml方式返回给client来解析。很明显,你要实现去数据库或者 其他的文件系统请求列表,你只要修改
    ConnectorServlet中两个私有方法:getFolders 和 getFiles
    让它去你指定的地方得到文件列表即可,这样你的文件可以放在任何你指定目录下。多说一句,很多人都想知道个人blog系统中怎么实现上传文件以后对应用户 浏览自己的列表的,我的做法很简单,建立你用户名的文件夹,你上传只能上传到你的目录夹,浏览可以通过程序指定浏览对应用户下的文件夹即可,这个时候你要 修改Connectorservlet中的路径即可!
    ------------------------------------
    2.超连接重定位问题
    ------------------------------------
    FCKeditor可以插入超连接,实现对文件的预览功能,只要我们稍微改变我们可以使FCKeditor编辑器支持对任意文件系统下的任意文件的客户端 浏览和下载保存!FCKeditor本来提供的是相对URL超链接,只要我们修改ConnectorServlet中传递给客户端的地址的时候,把它改写 成绝对URL然后再通过我们自己的filter的servlet实现重定向去一个下载/浏览文件的struts的action方法就可以实现在客户端对超 连接文件的下载和浏览!说一下具体做法吧:
    1):修改ConnectorServlet传递给客户端javascrīpt的路径,代码如下:
    String currentUrl = "http://"/ + request.getserver +request.getServerPort + request.getContextPath + resourcePath;
    以上代码请在ConnectorServlet的doGet()里面拼装!在调用CreateCommonXml()私有方法的时候参数传入:
    myEl.setAttribute("path",currentPath);
    myEl.setAttribute("url",currentUrl);
    提醒一下resourcePath为在web.xml配置文件中ConnectorServlet中的一个初始化参数配置,等一下利用filter实现对超连接的重定位就提取URL中的这个配置参数来判断,配置如下:
    <init-param>
        <param-name>resourcePath</param-name>
        <param-value>/fileSystem/</param-value>
    </init-param>
    2):建立你的filter servlet,实现对URL的截获,对符合要求的URL进行重定位到你的对应action中去即可
    3):实现你的对应action来实现文件的上传和下载功能即可!
    4):扩展功能-实现对URL的加密,对连接的URL中加上一串字符,最后几位作为算法校验,对不符合要求的URL连接,filter将会拒绝重定位到指 定action。此外利用自己写的扩展类还可以实现对超连接的文件类型进行限制,比如你只能超连接JPG|GIF|DOC|TXT|HTML等几种后缀名 的文件,对其他文件即使你指定超连接也让你浏览和下载,这些都可以在web.xml中通过修改对应servlet的配置文件的初始化参数实现。
    3.页面javascrīpt修改
    ------------------------------------
    浏览服务器的功能对应的html/javascrīpt相关的文件为:browser.html和frmresourcelist.html对应你想传递 的信息你可以append在文件名的字符串后面,在GetFileRowHtml()的javascrīpt函数中实现对文件名的截取,这样client 只会显示文件名,而你可以得到文件的数据库唯一标识,任何你想要的信息你都可以通过修改ConnectorServlet中的私有方法 getFiles()来实现,只要修改页面frmresurcelist.html中的GetFileRowHtml()中传入变量fileName即 可。你还可以在点击选中文件的时候实现一个你自己的Ajax调用,一切取决你的项目需要!
    4.我不是一个javascrīpt高手,其实如果我对javascrīpt了解多一些也许对客户端的代码修改以后做出更眩的功能。可以更好的完成对FCKeditor裁剪。
    -------------------------------------
    5.注意点
    -------------------------------------
    无论怎么修改别人的东西,请一定尊重开源精神!
    很多人配置好了FCKeditor的上传功能以后常会遇到xmlhttp request 404 error,后面是一串路径,其实就是你的servlet-mapping中的路径不对,你只要把xmlhttp request errot 404 后面跟的路径,copy到你的web.xml中对应红色文字的位置,如下:
    <servlet-mapping>
        <servlet-name>Connector</servlet-name>
        <url-pattern>/FCKeditor/editor/filemanager/browser/default/connectors/jsp/connector</url-pattern>
    </servlet-mapping>
    别忘了SimpleUploader的servlet-mapping也要做同样的修改!
    还有一个错误就是http 500错误,这个可能是你的URL请求不对,应该和FCKeditor没关系的!
    ======================================
    fckconfig.js总配置文件,可用记录本打开,修改后将文件存为utf-8 编码格式。找到:
    --------------------------------------
    FCKConfig.TabSpaces = 0;
    改为:
    FCKConfig.TabSpaces = 1;
    即在编辑器域内可以使用Tab键。
    如果你的编辑器还用在网站前台的话,比如说用于留言本或是日记回复时,那就不得不考虑安全了,
    在前台千万不要使用Default的toolbar,要么自定义一下功能,要么就用系统已经定义好的Basic,
    也就是基本的toolbar,找到:
    --------------------------------------
    FCKConfig.ToolbarSets["Basic"] = [
    ['Bold','Italic','-','OrderedList','UnorderedList','-',/*'Link',*/'Unlink','-','Style','FontSize','TextColor','BGColor','-',
    'Smiley','SpecialChar','Replace','Preview'] ];
    这是改过的Basic,把图像功能去掉,把添加链接功能去掉,因为图像和链接和flash和图像按钮添加功能都能让前台页直接访问和上传文件, fckeditor还支持编辑域内的鼠标右键功能。
    FCKConfig.ContextMenu = ['Generic',/*'Link',*/'Anchor',/*'Image',*/'Flash','Select','Textarea','Checkbox','Radio','TextField','HiddenField',
    /*'ImageButton',*/'Button','BulletedList','NumberedList','TableCell','Table','Form'];
    这也是改过的把鼠标右键的“链接、图像,FLASH,图像按钮”功能都去掉。
    找到:
    FCKConfig.FontNames = 'Arial;Comic Sans MS;Courier New;Tahoma;Times New Roman;Verdana';
    加上几种我们常用的字体
    FCKConfig.FontNames = '宋体;黑体;隶书;楷体_GB2312;Arial;Comic Sans MS;Courier New;Tahoma;Times New Roman;Verdana';
    添加文件 /TestFCKeditor/test.jsp:
    ----------------------------------------
    <%@ page language="java" import="com.fredck.FCKeditor.*" %>
    <%@ taglib uri="/TestFCKeditor" prefix="FCK" %>
    <script type="text/javascript" src="/TestFCKeditor/FCKeditor/fckeditor.js"></script>
    <%–
    三种方法调用FCKeditor
    1.FCKeditor自定义标签 (必须加头文件 <%@ taglib uri="/TestFCKeditor" prefix="FCK" %> )
    2.script脚本语言调用 (必须引用 脚本文件 <script type="text/javascript" src="/TestFCKeditor/FCKeditor/fckeditor.js"></script> )
    3.FCKeditor API 调用 (必须加头文件 <%@ page language="java" import="com.fredck.FCKeditor.*" %> )
    –%>
    <%–
    <form action="show.jsp" method="post" target="_blank">
        <FCK:editor id="content" basePath="/TestFCKeditor/FCKeditor/"
            width="700" height="500" skinPath="/TestFCKeditor/FCKeditor/editor/skins/silver/"
            toolbarSet = "Default">
            内容
        </FCK:editor>
        <input type="submit" value="Submit">
    </form>
    –%>
    <form action="show.jsp" method="post" target="_blank">
        <table border="0" width="700">
          <tr>
          <td>
            <textarea id="content" name="content" style="WIDTH: 100%; HEIGHT: 400px">input</textarea>
            <script type="text/javascript">
                  var oFCKeditor = new FCKeditor('content') ;
                  oFCKeditor.BasePath = "/TestFCKeditor/FCKeditor/" ;
                  oFCKeditor.Height = 400;
                  oFCKeditor.ToolbarSet = "Default" ;
                  oFCKeditor.ReplaceTextarea();
            </script>
            <input type="submit" value="Submit">
          </td>
          </tr>
        </table>
    </form>
    <%–
    <form action="show.jsp" method="post" target="_blank">
    <%
    FCKeditor oFCKeditor ;
    oFCKeditor = new FCKeditor( request, "content" ) ;
    oFCKeditor.setBasePath( "/TestFCKeditor/FCKeditor/" ) ;
    oFCKeditor.setValue( "input" );
    out.println( oFCKeditor.create() ) ;
    %>
    <br>
    <input type="submit" value="Submit">
    </form>
    –%>
    添加文件/TestFCKeditor/show.jsp:
    <%
    String content = request.getParameter("content");
    out.print(content);
    %>
    ====================================
    1、适时打开编辑器
    ------------------------------------
    很多时候,我们在打开页面的时候不需要直接打开编辑器,而在用到的时候才打开,这样一来有很好的用户体验,另一方面可以消除FCK在加载时对页面打开速度的影响,点击“Open Editor"按钮后才打开编辑器界面。
    实现原理:
    使用JAVASCRIPT版的FCK,在页面加载时(未打开FCK),创建一个隐藏的TextArea域,这个TextArea
    的name和ID要和创建的FCK实例名称一致,然后点击"Open Editor"按钮时,通过调用一段函数,使用
    FCK的ReplaceTextarea()方法来创建FCKeditor,代码如下:
    ------------------------------------
    <script type="text/javascript">
    <!–
    function showFCK(){
      var oFCKeditor = new FCKeditor( 'fbContent' ) ;
      oFCKeditor.BasePath = '/FCKeditor/' ;
      oFCKeditor.ToolbarSet = 'Basic' ;
      oFCKeditor.Width = '100%' ;
      oFCKeditor.Height = '200' ;
      oFCKeditor.ReplaceTextarea() ;
    }
    //–>
    </script>
    <textarea name="fbContent" id="fbContent"></textarea>
    2、使用FCKeditor 的 API
    -------------------------------------
    FCKeditor编辑器,提供了非常丰富的API,用于给End User实现很多想要定制的功能,比如最基本的数据验证,如何在提交的时候用JS判断当前编辑器区域内是否有内容,FCK的API提供了GetLength()方法;
    再比如如何通过脚本向FCK里插入内容,使用InsertHTML()等;
    还有,在用户定制功能时,中间步骤可能要执行FCK的一些内嵌操作,那就用ExecuteCommand()方法。
    详细的API列表,请查看FCKeditor的Wiki。而常用的API,请查看FCK压缩包里的_samples/html/sample08.html。此处就不贴代码了。
    3、外联编辑条(多个编辑域共用一个编辑条)
    --------------------------------------
    这个功能是2.3版本才开始提供的,以前版本的FCKeditor要在同一个页面里用多个编辑器的话,得一个个创建,现在有了这个外联功能,就不用那么麻烦了,只需要把工具条放在一个适当的位置,后面就可以无限制的创建编辑域了。
    要实现这种功能呢,需要先在页面中定义一个工具条的容器:<div id="xToolbar"></div>,然后再根据这个容器的id属性进行设置。
    JAVASCRIPT实现代码:
    --------------------------------------
    <div id="xToolbar"></div>
    FCKeditor 1:
    <script type="text/javascript">
    <!–
        // Automatically calculates the editor base path based on the _samples directory.
        // This is usefull only for these samples. A real application should use something like this:
        // oFCKeditor.BasePath = '/fckeditor/'; // '/fckeditor/' is the default value.
        var sBasePath = document.location.pathname.substring(0,document.location.pathname.lastIndexOf('_samples'));
        var oFCKeditor = new FCKeditor( 'FCKeditor_1' );
        oFCKeditor.BasePath = sBasePath;
        oFCKeditor.Height = 100;
        oFCKeditor.Config[ 'ToolbarLocation' ] = 'Out:parent(xToolbar)';
        oFCKeditor.Value = 'This is some <strong>sample text</strong>. You are using FCKeditor.';
        oFCKeditor.Create();
    //–>
    </script>
    <br />
    FCKeditor 2:
    <script type="text/javascript">
    <!–
        oFCKeditor = new FCKeditor( 'FCKeditor_2' );
        oFCKeditor.BasePath = sBasePath;
        oFCKeditor.Height = 100;
        oFCKeditor.Config[ 'ToolbarLocation' ] = 'Out:parent(xToolbar)';
        oFCKeditor.Value = 'This is some <strong>sample text</strong>. You are using FCKeditor.';
        oFCKeditor.Create();
    //–>
    </script>
    -------------------------------------
    此部分的详细DEMO请参照_samples/html/sample11.html,_samples/html/sample11_frame.html
    4、文件管理功能、文件上传的权限问题
    -------------------------------------
    一直以来FCKeditor的文件管理部分的安全是个值得注意,但很多人没注意到的地方,虽然FCKeditor在各个Release版本中一直存在的一个功能就是对上传文件类型进行过滤,但是她没考虑过另一个问题:到底允许谁能上传?到底谁能浏览服务器文件?
    之前刚开始用FCKeditor时,我就出现过这个问题,还好NetRube(FCKeditor中文化以及FCKeditor ASP版上传程序的作者)及时提醒了我,做法是去修改FCK上传程序,在里面进行权限判断,并且再在fckconfig.js里把相应的一些功能去掉。但 随之FCK版本的不断升级,每升一次都要去改一次配置程序fckconfig.js,我发觉厌烦了,就没什么办法能更好的控制这种配置么?事实上,是有 的。
    在fckconfig.js里面,有关于是否打开上传和浏览服务器的设置,在创建FCKeditor时,通过程序来判断是否创建有上传浏览功能的编辑器。首先,我先在fckconfig.js里面把所有的上传和浏览设置全设为false,接着我使用的代码如下:
    JAVASCRIPT版本:
    -------------------------------------
    <script type="text/javascript">
        var oFCKeditor = new FCKeditor( 'fbContent' );
        <% if power = powercode then %>
        oFCKeditor.Config['LinkBrowser'] = true;
        oFCKeditor.Config['ImageBrowser'] = true;
        oFCKeditor.Config['FlashBrowser'] = true;
        oFCKeditor.Config['LinkUpload'] = true;
        oFCKeditor.Config['ImageUpload'] = true;
        oFCKeditor.Config['FlashUpload'] = true;
        <% end if %>
        oFCKeditor.ToolbarSet = 'Basic';
        oFCKeditor.Width = '100%';
        oFCKeditor.Height = '200';
        oFCKeditor.Value = '';
        oFCKeditor.Create();
    </script>
    -------------------------------------
    在按钮旁边加文字
    -------------------------------------
    打开 editor/js/ 两个js文件
    fckeditorcode_gecko.js
    fckeditorcode_ie.js
    第一个是支持非ie浏览器的
    第二个文件是支持ie浏览器的
    搜索 FCKToolbarButton,可以看到许多类似这样的语句:
    case 'Save':B = new FCKToolbarButton('Save', FCKLang.Save, null, null, true, null, 3); break;
    'Save'是按钮英文名字
    FCKToolbarButton 的四个参数分别是:
    按钮命令名称,按钮标签文字,按钮工具提示,按钮样式,按钮是否在源代码模式可见,按钮下拉菜单其中将第4项参数设置为 FCK_TOOLBARITEM_ICONTEXT 即可使按钮旁边出现文字,注意没有引号。
    例如:
    case 'Preview':B = new FCKToolbarButton('Preview', FCKLang.Preview, null, FCK_TOOLBARITEM_ICONTEXT, true, null, 5);
    这样我们就可以将 我们经常用的3种模式源代码、预览、全屏编辑按钮都加上文字了。
    解释fck样式的工作原理
    -------------------------------------
    fck的样式设置涉及到了两个文件,一个是你定义好的样式表文件.css,另一个是告诉fck样式表如何使用的xml文件,两个文件确一不可。
    css文件的位置是不做要求的,但是需要你在应用的编辑器的页面上插入样式表文件的链接。这样才能显示出来样式。
    fckstyles.xml 在与editor目录同级的目录下。该文件定义了那些样式可以使用在那些标签里面。
    这就是fck自带的样式xml定义:
    <?xml version="1.0" encoding="utf-8" ?>
    <Styles>
      <Style name="Image on Left" element="img">
        <Attribute name="style" value="padding: 5px; margin-right: 5px" />
        <Attribute name="border" value="2" />
        <Attribute name="align" value="left" />
      </Style>
      <Style name="Image on Right" element="img">
        <Attribute name="style" value="padding: 5px; margin-left: 5px" />
        <Attribute name="border" value="2" />
        <Attribute name="align" value="right" />
      </Style>
      <Style name="Custom Bold" element="span">
        <Attribute name="style" value="font-weight: bold;" />
      </Style>
      <Style name="Custom Italic" element="em" />
      <Style name="Title" element="span">
        <Attribute name="class" value="Title" />
      </Style>
      <Style name="Code" element="span">
        <Attribute name="class" value="Code" />
      </Style>
      <Style name="Title H3" element="h3" />
      <Style name="Custom Ruler" element="hr">
        <Attribute name="size" value="1" />
        <Attribute name="color" value="#ff0000" />
      </Style>
    </Styles>
    每一个<style>将来会生成一个样式的菜单项。name名称就是显示在菜单里的文字;element定义了该样式可以应用在那种html 标签上,<Attribute>的 name 指定了将会修改标签的哪个属性来应用样式,value则是修改成的值。
    看这个:
    <Style name="Title" element="span">
      <Attribute name="class" value="Title" />
    </Style>
    如果你在fck选定了文字 “经典论坛 》 前台制作与脚本专栏 》 FCKeditor 实战技巧 – 1 》 编辑帖子” 应用该样式 则原来文字就会变成<span class="Title">经典论坛 》 前台制作与脚本专栏 》 FCKeditor 实战技巧 – 1 》 编辑帖子</span>
    注意:如果编辑器呈整页编辑状态,那么整页里面也需要插入样式表链接才能显示出来样式。
    ============================================
    FCKeditor JavaScript API(翻译整理)
    原文地址:http://wiki.fckeditor.net/Developer's_Guide/Javascript_API
    --------------------------------------------
    FCK 编辑器加载后,将会注册一个全局的 FCKeditorAPI 对象。
    FCKeditorAPI 对象在页面加载期间是无效的,直到页面加载完成。如果需要交互式地知道 FCK 编辑器已经加载完成,可使用“FCKeditor_OnComplete”函数。
    <script type="text/javascript">
    function FCKeditor_OnComplete(editorInstance) {
      FCKeditorAPI.GetInstance('FCKeditor1').Commands.GetCommand('FitWindow').Execute();
    }
    </script>
    在当前页获得 FCK 编辑器实例:
    var oEditor = FCKeditorAPI.GetInstance('InstanceName');
    从 FCK 编辑器的弹出窗口中获得 FCK 编辑器实例:
    var oEditor = window.parent.InnerDialogLoaded().FCK;
    从框架页面的子框架中获得其它子框架的 FCK 编辑器实例:
    var oEditor = window.FrameName.FCKeditorAPI.GetInstance('InstanceName');
    从页面弹出窗口中获得父窗口的 FCK 编辑器实例:
    var oEditor = opener.FCKeditorAPI.GetInstance('InstanceName');
    获得 FCK 编辑器的内容:
    oEditor.GetXHTML(formatted); // formatted 为:true|false,表示是否按HTML格式取出
    也可用:
    oEditor.GetXHTML();
    设置 FCK 编辑器的内容:
    oEditor.SetHTML("content", false); // 第二个参数为:true|false,是否以所见即所得方式设置其内容。此方法常用于“设置初始值”或“表单重置”操作。
    插入内容到 FCK 编辑器:
    oEditor.InsertHtml("html"); // "html"为HTML文本
    检查 FCK 编辑器内容是否发生变化:
    oEditor.IsDirty();
    在 FCK 编辑器之外调用 FCK 编辑器工具条命令:
    命令列表如下:
    --------------------------------------------
    DocProps, Templates, Link, Unlink, Anchor, BulletedList, NumberedList, About, Find, Replace, Image, Flash, SpecialChar, Smiley, Table, TableProp, TableCellProp, UniversalKey, Style, FontName, FontSize, FontFormat, Source, Preview, Save, NewPage, PageBreak, TextColor, BGColor, PasteText, PasteWord, TableInsertRow, TableDeleteRows, TableInsertColumn, TableDeleteColumns, TableInsertCell, TableDeleteCells, TableMergeCells, TableSplitCell, TableDelete, Form, Checkbox, Radio, TextField, Textarea, HiddenField, Button, Select, ImageButton, SpellCheck, FitWindow, Undo, Redo
    --------------------------------------------
    使用方法如下:
    --------------------------------------------
    oEditor.Commands.GetCommand('FitWindow').Execute();
    --------------------------------------------

     

    [转自http://lingoosoft.blog.ccidnet.com/blog-htm-do-showone-uid-37700-type-blog-itemid-121211.html]

    [C#]P2P通讯初步实现(c#,Socket连接)

    mikel阅读(1120)

    1:基于Socket连接;

    2:在四个局域网内测试通过;

    3:简单模型,需要进一步优化效率和处理;

     

    基本思路

    两个分别在不同的局域网内的用户无法直接建立连接并通讯。因为处在不同局域网的用户(没有公共IP)无法被外部机器主动连接,所以凡是所谓的P2P一般都是通过中间服务器中转通讯的。比如在几年前俺曾经介绍过一个P2P的软件,http://www.cnblogs.com/dlwang2002/archive/2005/04/14/207988.html,基本原理那里面有介绍。

    这次所建立的模型,是双方都在不同的局域网内部,都没有公用IP

    基本原理是这样的。局域网A内用户PA想要和局域网B内的用户PB通讯,那么需要通过中间服务器S进行转接通讯。Socket链接虽然只是由一方发起(局域网内的),但是socket确实一个可以在两端都能通讯的,也就是说,PA链接S后,S实际上可以使用这个通道直接发消息给PA。同理,如果PB连接之后,S将有两个Socket实例,然后S可以把SA的消息直接转发给SB,这样SB就转载了SA的请求到了PB。虽然还是要通过中转,但是S只负责把两端Socket互联,速度延时可近似认为是0,也就是可以认为PAPB是建立了直接的链接,P2P

    过程如下:

    1:)PAS发出连接请求;S接受请求,并且保留住PAsocket实例SA,存进一个在线用户列表LiveConnections

    2:)PB请求S并建立连接(和A无先后关系),S中保存其socket实例SB

    3:)PAs发出通讯请求,指明通讯对象是PB

    4:)S接收到A的请求,再当前的LiveConnections中找到PBsocket示例SB,转发消息;

    5:)PB接受到来自PA的消息。

     

     

    主要程序代码

       1:)首先的问题是如何建立Socket连接。这个问题在以前的一篇Blog中有提到(http://www.cnblogs.com/dlwang2002/archive/2008/07/21/924803.html)。这里使用的代码基本上都是和那一个一样的,只有中间处理通讯数据的部分稍有不同。这些代码不再赘述。

       2:)服务器S处理转发消息的代码

                     

    Code

       3:)客户端的简单实现

     

    ConnectionManager

        
      4:)UI等其他处理 (略)

     

    问题

    1:)一个Socket的实例可以在服务器/客户端存活多久呢?我测试发现,至少几个小时没有问题,但是最长时间却不知道。

        2:)服务器S用单独的线程来处理链接,并不是最好的方式

        3:)服务器负载平衡,在多个服务器的情况下,要让客户端可以选择效率最高的服务器进行中转

        4:)有一台机器已经在公网上,或者两台都在公网上,需要另外的模型。他们不需要中转。

     

    小结

        简单,效率未知。
    server.jpg
    client.jpg

    [JavaScript]简易而又灵活的Javascript拖拽框架(三)

    mikel阅读(765)

    一、开篇

         这是这个拖拽系列的第三篇了,第一篇简单的介绍了一下这个拖拽框架,第二篇用这个框架做了一个Tab标签的拖放。这次用这个拖拽框架做一个更复杂一点的效果——跨列拖放。就像iGoogle和netvibes的个性页面布局那样。

     

    二、原理

     框架在第一篇做了介绍,这里直接使用。

    首先要找到每个可以拖动的item,对于每个拖动的item,对其注册组件Drag.init(handle,dragBody);并且要把这个对象所在的列赋值给这个对象

    还是分三个步骤说这个拖放的过程

    1、鼠标拖动开始的时候,除了要将dragGhost放到当前被拖动的对象原来的位置上,还要记录每一列的左边距,当然还是要设置被拖动对象的position

     

    2、鼠标拖动的过程中

    先找到拖动对象是在哪一列,通过现在拖动对象的位置和在拖动开始时记录的列的左边距相比较,得出当前拖动对象在哪一列。


     

    如果在原来那一列上,则不用管了,如果在别的列上,则将dragGhost插入到这个新的列中去(用column.appendChild插入到最后)。无论是本来就在这一列的元素还是从别的列拖过来的元素,都得让拖动对象与他所在的列的每一个元素的纵坐标相比较,得出应该在这一列的什么位置,将dragGhost插入(用column.insertBefore)。至于怎么找到拖动元素应该放在这一列的什么位置,这个原理和上边找列的原理差不多,只是比较的是纵坐标的值,比较的对象是本列的所有对象(注意,遍历的时候一定要排除dragGhost和本身,要不然在本列不能向下拖动)。

    3、拖动完成

    ghost替换为被拖动的元素,设置相应的样式

    三、代码

    Code

     如果这样不方便观看,可以下载示例。

    四、示例下载

          点此下载示例

    [JavaScript]简易而又灵活的Javascript拖拽框架(二)

    mikel阅读(765)

    一、开篇

    在上一篇中,似乎不出来这个框架有多强大。是因为我们实现的效果太简单了,还不足以体现框架的强大和灵活,在这一节中,用这个灵活的框架轻易的来实现拖放!

     

    二、原理

     

    框架的原理在上一篇文章中介绍了,这里就不在重复,直接开始使用这个框架了

    首先通过Drag.init来注册拖动组件;

    分析:

    1、拖动开始的时候

    dragGhost插入到鼠标拖动的那个元素,鼠标拖动的元素的positionabsolute

    dragGhost为拖动过程中指示拖动元素的当前位置的元素

    2、拖动正在进行的时候

    根据当前鼠标的位置或者正在被鼠标拖动的元素的位置 和需要排列的各种元素来比较,以确定将dragGhost放在哪个地方。

    具体的分析,就是遍历拖动元素的各个兄弟元素,从第一元素起,一旦发现某个元素的xy比鼠标的xy大的话,则将dragGhost添加到这个元素之前。

    3、拖动结束的时候

    dragGhost替换为被拖动的元素,然后将dragGhost隐藏。

     

    这样就让思路很清晰,不必再花精力去管元素是怎么随着鼠标走的,而且我们的却很精确的控制了整个拖放过程,所以说这个框架很强大很灵活

    三、代码

    Code

     

    四、示例下载

          点此下载示例

    [JavaScript]简易而又灵活的Javascript拖拽框架(一)

    mikel阅读(772)

    一、开篇

    最近在做js拖拽的时候,发现了一个强大而又灵活的拖拽框架,(之前用了代码混淆器,还好代码比较短,我就翻译过来了)利用这个框架不仅能实现简单的拖动,更能轻易的实现各种复杂的拖放功能。这一篇先实现最简单的拖拽,稍微复杂的拖放将在后面的文章里写出来。

    二、代码

    先把代码贴出来


    var Drag={
        
    "obj":null,
        
    "init":function(handle, dragBody, e){
            
    if (e == null) {
                handle.onmousedown
    =Drag.start;
            }
            handle.root 
    = dragBody;
            
            
    if(isNaN(parseInt(handle.root.style.left)))handle.root.style.left="0px";
            
    if(isNaN(parseInt(handle.root.style.top)))handle.root.style.top="0px";//确保后来能够取得top值
            handle.root.onDragStart=new Function();
            handle.root.onDragEnd
    =new Function();
            handle.root.onDrag
    =new Function();
            
    if (e !=null) {
                
    var handle=Drag.obj=handle;
                e
    =Drag.fixe(e);
                
    var top=parseInt(handle.root.style.top);
                
    var left=parseInt(handle.root.style.left);
                handle.root.onDragStart(left,top,e.pageX,e.pageY);
                handle.lastMouseX
    =e.pageX;
                handle.lastMouseY
    =e.pageY;
                document.onmousemove
    =Drag.drag;
                document.onmouseup
    =Drag.end;
            }
        },
        
    "start":function(e){
            
    var handle=Drag.obj=this;
            e
    =Drag.fixEvent(e);
            
    var top=parseInt(handle.root.style.top);
            
    var left=parseInt(handle.root.style.left);
            
    //alert(left)
            //一般情况下 left top 在初始的时候都为0
            handle.root.onDragStart(left,top,e.pageX,e.pageY);
            handle.lastMouseX
    =e.pageX;
            handle.lastMouseY
    =e.pageY;
            document.onmousemove
    =Drag.drag;
            document.onmouseup
    =Drag.end;
            
    return false;
        },    
        
    "drag":function(e){//这里的this为document 所以拖动对象只能保存在Drag.obj里
            e=Drag.fixEvent(e);
            
    var handle=Drag.obj;
            
    var mouseY=e.pageY;
            
    var mouseX=e.pageX;
            
    var top=parseInt(handle.root.style.top);
            
    var left=parseInt(handle.root.style.left);//这里的top和left是handle.root距离浏览器边框的上边距和左边距
            
            
    var currentLeft,currentTop;
            currentLeft
    =left+mouseXhandle.lastMouseX;
            currentTop
    =top+(mouseYhandle.lastMouseY);
            
            
    //上一瞬间的上边距加上鼠标在两个瞬间移动的距离 得到现在的上边距
            
            handle.root.style.left
    =currentLeft +"px";
            handle.root.style.top
    =currentTop+"px";
            
            
    //更新当前的位置
            
            handle.lastMouseX
    =mouseX;
            handle.lastMouseY
    =mouseY;
            
            
    //保存这一瞬间的鼠标值 用于下一次计算位移
            
            handle.root.onDrag(currentLeft,currentTop,e.pageX,e.pageY);
    //调用外面对应的函数
            return false;
        },
        
    "end":function(){
            document.onmousemove
    =null;
            document.onmouseup
    =null;
            Drag.obj.root.onDragEnd(parseInt(Drag.obj.root.style.left),parseInt(Drag.obj.root.style.top));
            Drag.obj
    =null;
        },
        
    "fixEvent":function(e){//格式化事件参数对象
            if(typeof e=="undefined")e=window.event;
            
    if(typeof e.layerX=="undefined")e.layerX=e.offsetX;
            
    if(typeof e.layerY=="undefined")e.layerY=e.offsetY;
            
    if(typeof e.pageX == "undefined")e.pageX = e.clientX + document.body.scrollLeft  document.body.clientLeft;
            
    if(typeof e.pageY == "undefined")e.pageY = e.clientY + document.body.scrollTop  document.body.clientTop;
            
    return e;
        }
    };

    使用方法

    Drag.init(handle,dragBody);这样可以让鼠标拖动元素。Handle为拖动的把手,dragBody是在拖动时需要移动的元素。

     

    如果需要更高级的控制拖动或者拖放的话,可以给dragBody设置三个方法

    dragBody.onDragStart=function(left,top,mouseX,mouseY){}

    onDragleft,top,mouseX,mouseY){}

    onDragEndleft,top,mouseX,mouseY){}

    这四个参数分别 是:拖动对象的left属性、拖动对象的top属性(此时拖动对象的position为absolute)、鼠标当前的x、鼠标当前的y。在每个过程中都 可以通过四个参数来更精确的控制拖动的每个过程,更主要的是我们不需要去管被鼠标拖动的元素是怎么移动的,这些都在框架中已经做好了,这让拖拽看起来更整 洁。框架具体是怎么运转的,其实很简单

     

    三、原理

    Drag有几个成员

    Drag.obj用来存放鼠标正在被拖动的元素,只有在鼠标按下过后才会赋值,鼠标松开便为空了。便于在这几个方法之间都能够轻易的找到正在被拖动的元素。

    Drag.init主要是用来订阅handleonmousedown事件,所以handle一旦点击,则会执行Drag.start方法。

    Drag.start是用来注册documentmousemovemouseup事件的,而且会调用我们定义的dragBody.onDragStart方法(这里的dragBody就是通过Drag.obj来获得的),以便处理框架以外需要处理的事情。

    Mousemove的时候会不断的触发Drag.drag方法,这个方法主要是控制dragBody的移动(通过前后两个瞬间的位移差来调整dragBody的位置),以及调用外部的dragBody.onDrag方法,处理框架以外的事情。

    Documentmouseup方法,调用外部的onDragEnd方法,释放document绑定的两个事件,以及将临时的obj置为空

    四、示例下载

     点此下载示例

    [C#]调用Master Page的属性和方法

    mikel阅读(1258)

        ((命名空间.母板的类)(this.Page.Master)).属性 = "你好";
    例如:
    //用于读取JobSeeker Master的IsLogin属性
    (( NewTang.Views.Shared.JobSeeker)this.Page.Master).IsLogin;

    1.缓存使用:
     在使用master页面时,不能把高速缓存只应用与master页面,不能把OutputCache指令放到master页面上。如果这么做,在页面的第二次检索时,就会报错。因为应用程序找不到缓存页面.

    2.在内容页中编写代码来引用母版页中的属性、方法和控件:

    可以在内容页中编写代码来引用母版页中的属性、方法和控件,但这种引用有一定的限制。对于属性和方法的规则是:如果它们在母版页上被声明为公共成员,则可以引用它们。这包括公共属性和公共方法。在引用母版页上的控件时,没有只能引用公共成员的这种限制。

    引用母版页上的公共成员

    1. 在内容页中添加 @ MasterType 指令。在该指令中,将 VirtualPath 属性设置为母版页的位置,如下面的示例所示:

      <%@ MasterType virtualpath="~/Masters/Master1.master" %>

      此指令使内容页的 Master 属性被强类型化。

    2. 编写代码,将母版页的公共成员用作 Master 属性的一个成员,如本例中,将母版页名为 CompanyName 的公共属性的值赋给内容页上的一个文本框:

    引用母版页上的控件

    • 使用 FindControl 方法,将 Master 属性的返回值用作命名容器。

      下面的代码示例演示如何使用 FindControl 方法获取对母版页上的两个控件的引用(一个 TextBox 控件和一个 Label 控件)。因为 TextBox 控件处在 ContentPlaceHolder 控件的内部,必须首先获取对 ContentPlaceHolder 的引用,然后使用其 FindControl 方法来定位 TextBox 控件。

    • void Page_Load()
          {
          // Gets a reference to a TextBox control inside
          // a ContentPlaceHolder
          ContentPlaceHolder mpContentPlaceHolder;
          TextBox mpTextBox;
          mpContentPlaceHolder =
          (ContentPlaceHolder)Master.FindControl("ContentPlaceHolder1");
          if(mpContentPlaceHolder != null)
          {
          mpTextBox =
          (TextBox) mpContentPlaceHolder.FindControl("TextBox1");
          if(mpTextBox != null)
          {
          mpTextBox.Text = "TextBox found!";
          }
          }
          // Gets a reference to a Label control that not in
          // a ContentPlaceHolder
          Label mpLabel = (Label) Master.FindControl("masterPageLabel");
          if(mpLabel != null)
          {
          Label1.Text = "Master page label = " + mpLabel.Text;
          }
          }

    [SQL]SQL Server2005的Top n PERCENT的说明

    mikel阅读(949)

    使用TOP   n   [PERCENT]选项限制返回的数据行数,TOP   n说明返回n行,而TOP   n   PERCENT时,说明n是表示一百分数,指定返回的行数等于总行数的百分之几。  
      使用技巧:  
      SQL   Server   2000不允许在视图、嵌入式UDF、子查询中出现ORDER   BY子句,因为它们都应该返回一个表,表不能指定行的次序。然而,如果使用了TOP关键词,ORDER   BY子句将帮助确定查询所返回的行。因此,如果指定了TOP,你还可以同时指定ORDER   BY。由于在带有TOP的UDF中允许使用ORDER   BY子句,你可以使用一个技巧:把“Select   *”替换成“Select   TOP   100   PERCENT   *”。这样,你就能够成功地构造出一个接受列名字或编号为参数、返回排序结果的函数。