[转载]MongoDB on Asp.Net MVC3

mikel阅读(1101)

[转载]MongoDB on Asp.Net MVC3 – Pandora – 博客园.

晚上闲来无事,研究了一下最近很火的MongoDB。感受只有一个:“自由”。

闲话略过,先让MongoDB在Win7 64下跑起来:

1. MongoDB主页

http://www.mongodb.org/

2. 下载

http://downloads.mongodb.org/win32/mongodb-win32-x86_64-1.8.1.zip

3. 解压

e.g. H:\mongodb-win32-x86_64-1.8.1

4. 准备目录

e.g. H:\mongo\data –保存数据库文件 H:\mongo\logs –保存log,在此目录下手动创建一个log.txt

5. 安装

Win键,输入cmd,右键-Run as Administrator

cd H:\mongodb-win32-x86_64-1.8.1\bin

H:

mongod –bind_ip 127.0.0.1 –logpath H:\mongo\logs\log.txt –logappend –dbpath H:\mongo\data –directoryperdb –install

net start “MongoDB”

成功。

6. 测试安装

在之前的CMD窗口中输入:mongo

应该能无异常进入query界面

输入一个3+3,应该能得到6

关掉cmd,这玩意儿没用了。

7. 下载.Net Connector

https://github.com/mongodb/mongo-csharp-driver/archives/master

解压

打开CSharpDriverSetup-2010.sln

Build

失败

删除DriverSetup中对CHM的引用

重新编译,成功

右键DriverSetup – Install

下一步下一步下一步。。。

8. 创建ASP.NET MVC3 Empty project

若无,请自行安装MVC3的TOOL

9. Add ConnectionString in web.config




10. Add Controller

Controller with empty read/write actions

11. Access to the DB

private MongoDatabase GetDB()
{
return MongoDatabase.Create(ConfigurationManager.ConnectionStrings["MongoDB"].ConnectionString);

}

12. Create Action

[HttpPost]

public ActionResult Create(FormCollection collection)
{
try
{
var db = GetDB();
foreach (var key in collection.AllKeys)
{
db["testTable"].Insert(new MongoDB.Bson.BsonDocument{
{key, collection[key]}
});
}

return RedirectToAction("Index");
}
catch
{
return View();
}
}

13. Index Action

public ActionResult Index()
{
try
{
var db = GetDB();

var testTable = db["testTable"].FindAll();
var result = new StringBuilder();
foreach (var testData in testTable)
{
foreach (var property in testData.Names)
{
result.AppendFormat("{0}:{1} ", property, testData[property]);
}

result.Append("
");
}

return Content(result.ToString());
}
catch
{
return View();
}
}

14. Create Views under Views/Home/
Create.cshtml:

@{
ViewBag.Title = "Create";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Create</h2>
<form action="/Home/Create" method="post"> Name:
<input name="name" type="text" />

Age:
<input name="age" type="text" />

Gender:
<input name="gender" type="text" />

Married:
<input name="married" type="text" />

<input type="submit" value="Add" />
</form>

Index.cshtml

@{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Index</h2>
<a href="Create">Create New</a>

15. Modify Global.asax.cs

routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Create", id = UrlParameter.Optional } // Parameter defaults
);
11. Build & Run
image

Press Add

image

All Done. Happy and enjoy.

补上项目下载:

http://files.cnblogs.com/pandora/MvcApplication1.zip

IIS网站日志分析方法概述 怎样变得更简单更有价值

mikel阅读(909)

转载:http://www.admin5.com/article/20110525/346051.shtml

日志在计算机系统中是一个非常广泛的概念,任何程序都有可能输出日志:操作系统内核、各种应用服务器等等。日志的内容、规模和用途也各不相同,很难一概而论。

本文讨论的日志处理方法中的日志,仅指Web日志。其实并没有精确的定义,可能包括但不限于各种前端Web服务器——apache、lighttpd、tomcat等产生的用户访问日志,以及各种Web应用程序自己输出的日志。

在Web日志中,每条日志通常代表着用户的一次访问行为,例如下面就是一条典型的apache日志:

211.87.152.44 – – [18/Mar/2005:12:21:42 +0800] “GET / HTTP/1.1″ 200 899 “http://www.baidu.com/” “Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Maxthon)”

从上面这条日志中,我们可以得到很多有用的信息,例如访问者的IP、访问的时间、访问的目标网页、来源的地址以及访问者所使用的客户端的 UserAgent信息等。如果需要更多的信息,则要用其它手段去获取:例如想得到用户屏幕的分辨率,一般需要使用js代码单独发送请求;而如果想得到诸 如用户访问的具体新闻标题等信息,则可能需要Web应用程序在自己的代码里输出。

为什么要分析日志

毫无疑问,Web日志中包含了大量人们——主要是产品分析人员会感兴趣的信息,最简单的,我们可以从中获取网站每类页面的PV值 (PageView,页面访问量)、独立IP数(即去重之后的IP数量)等;稍微复杂一些的,可以计算得出用户所检索的关键词排行榜、用户停留时间最高的 页面等;更复杂的,构建广告点击模型、分析用户行为特征等等。

既然这些数据是如此的有用,那么当然已经有无数现成的工具可以帮助我们来分析它们,例如awstats、Webalizer,都是专门用于统计分析Web服务器日志的免费程序。

另外还有一类产品,它们不分析直接日志,而是通过让用户在页面中嵌入js代码的方式来直接进行数据统计,或者说我们可以认为它是直接让日志输出到了它们的服务器。典型的代表产品——大名鼎鼎的Google Analytics,另外还有国内的cnzz、百度统计等。

很多人可能会说,既然如此,我们为什么还需要自己来分析日志,有必要吗?当然有。我们的用户(产品分析人员)需求是无穷尽的,上面说的这几类工具虽然很好很强大,但显然没办法满足全部的需求。

无论是本地分析的工具,还是在线的分析服务,它们虽然提很丰富的的统计分析功能,可以做一定程度的配置,但是依然很有限的。要进行稍复杂点的分析,或者要做基于日志的数据挖掘,依然需要自己来完成。

另外绝大多数日志分析工具都是只能用于单机的,数据量稍大就没辙了。同时那些提供在线分析的服务对于单个站点通常也都有最大流量的限制——这是很容易理解的,他们也需要考虑服务器的负载。

所以,很多时候还是得靠自己。

怎么进行日志分析

这并不是一个简单的问题。即使我们把“日志”限定为Web日志,依然包含了成千上万种可能的格式和数据,而是“分析”更是难以定义,也许是简单的统计值的计算,也许是复杂的数据挖掘算法。

下面并不打算讨论这些复杂的问题,而只是笼统的讨论如何构建进行日志分析工作的基础。有了这些基础会让基于日志的简单统计分析变得很简单,并让复杂的分析挖掘等变得可行。

少量数据的情况

先考虑最简单的情况,在数据规模比较小的时候,也许是几十MB、几百MB或者几十GB,总之就是在单机处理尚能忍受的时候。一切都很好办,现成 的各种Unix/Linux工具——awk、grep、sort、join等都是日志分析的利器,如果仅仅是想知道某个页面的PV,一个wc+grep就 能搞定。如果有稍复杂的逻辑,那就使用各种脚本语言,尤其是perl,配合伟大的正则表达式,基本就可以解决所有的问题。

例如,我们想从上面提到的apache日志中得到访问量最高前100个IP,实现很简单:

cat logfile | awk ‘{a[$1]++} END {for(b in a) print b”\t”a[b]}’|sort -k2 -r|head -n 100

不过当我们需要频繁去分析日志的时候,上面的做法在一段时间之后可能就会让我们头疼如何进行各种日志文件、用于分析的脚本文件、crontab文件等等的维护,并且可能会存在大量重复的代码来做数据格式的解析和清洗,这个时候也许就需要更合适的东西,比如——数据库。

当然,要使用数据库来进行日志分析还是需要一些代价的,最主要的就是如何将各种异构的日志文件导入的数据库中——这个过程通常称为 ETL(Extraction-Transformation-Loading)。幸好依然有各种现成的开源、免费的工具来帮助我们做这件事情,并且在日 志种类不太多的时候,自己写几个简单的脚本来完成这项工作也并不困难。例如可以将上面的日志去掉不必要的字段,然后导入如下的数据库中:

现在需要考虑一下用什么数据库来存储这些数据。MySQL是一个很经典的开源数据库,它的传统引擎(MyISAM或者InnoDB,行存储)也 许并不非常的适合日志数据的存储,但是在小数据量的时候还是很够用的。而且,在这方面现在已经有了更好的选择,例如开源且免费的Infobright、 Infinidb,都是专门为数据仓库应用而进行了优化的数据引擎,采用列存储,有良好的数据压缩,处理几百GB的数据基本上不是问题。

使用数据库的好处之一就是,伟大的SQL可以帮我们很简单的完成绝大部分的统计分析工作——PV只需要SELECT+COUNT,计算搜索词排 行只需要SELECT+COUNT+GROUP+ORDER+LIMIT。此外,数据库本身的结构化存储模式也让日志数据的管理变的更简单,减少运维代 价。

同样还是上面的那个例子,简单的一个SQL就可以搞定:

SELECT * FROM (SELECT ip, COUNT(*) AS ip_count FROM apache_log GROUP BY ip) a ORDER BY ip_count DESC LIMIT 100

至于性能问题,数据库的索引和各种优化机制通常会让我们的统计分析工作变得更快,并且上面提到的Infobright和Infinidb都专门 为类似SUM、COUNt之类的聚集应用做了优化。当然也不是绝对的会快,例如在数据库中进行LIKE操作,通常会比grep一个文件还要慢很多。

更进一步的,使用基于数据库的存储,可以很容易的进行OLAP(联机分析处理)应用,从日志中挖掘价值会变的更加简单。

更多的数据怎么办

一个好的数据库似乎会让事情变的很简单,但是别忘了前面提到的都是单机数据库。一台单机在存储容量、并发性上毫无疑问都是有很大限制的。而日志 数据的特点之一就是随时间持续增长,并且由于很多分析过程往往需要历史数据。短时间内的增长也许可以通过分库、分表或者数据压缩等来解决,不过很显然并不 是长久之计。

想要彻底解决数据规模增长带来的问题,很自然的会想到使用分布式技术,结合上面的结论,也许使用某个分布式数据库是一个好选择,那么对最终用户就可以完全透明了。这个的确是很理想的情况,不过现实往往是残酷的。

首先,实现比较完美的分布式数据库(受限于CAP原则)是一个非常复杂的问题,因此在这里并不像单机数据库那样,有那么多开源的好东西可以用, 甚至于商用的也并不是太多。当然,也并非绝对,如果有钱,还是可以考虑一下Oracle RAC、Greenplum之类东西。

其次,绝大多数分布式数据库都是NoSQL的,所以想继续用上SQL的那些优点基本上是没指望,取而代之的都是一些简单、难以使用的接口。单从这点看来,使用这些数据库的价值已经降低很多了。

所以,还是先现实一点,先退一步考虑如何解决的超大规模的日志的分析问题,而不是想如何让它变的像在小数据规模时那样简单。单单想做到这点,目前看来并不是太难,并且依然有免费的午餐可以吃。

Hadoop是伟大的Apache基金会下面的一套分布式系统,包括分布式文件系统(HDFS)、MapReduce计算框架、HBase等很多组件——这些基本都是Google的GFS/MapReduce/BigTable的克隆产品。

Hadoop经过数年的发展,目前已经很成熟了,尤其是其中的HDFS和MapReduce计算框架组件。数百台机器的集群已经被证明可以使用,可以承担PB级别的数据。

Hadoop项目中的HBase是一个按列存储的NoSQL分布式数据库,它提供的功能和接口都非常简单,只能进行简单的K-V查询,因此并不 直接适用于大多数日志分析应用。所以一般使用Hadoop来做日志分析,首先还是需要将日志存储在HDFS中,然后再使用它提供的MapReduce API编写日志分析程序。

MapReduce是一种分布式编程模型,并不难学习,但是很显然使用它来处理日志的代价依然远大于单机脚本或者SQL。一个简单的词频统计计算可能都需要上百代码——SQL只需要一行,另外还有复杂的环境准备和启动脚本。

例如同样还是上面的例子,实现就要复杂的多,通常需要两轮MapReduce来完成。首先要在第一轮的mapper中计算部分ip的访问次数之和,并以ip为key输出:

//遍历输入,并聚合结果

foreach(record in input) {

ip = record.ip;

dict[ip]++;

}

//用emit输出,第一个参数为key,用于reduce的分发

foreach( in dict) {

emit(ip, count);

}

然后在第一轮的reduce中就可以得到每个ip完整的计数,可以顺便排个序,并且只保留前100个。

count = 0;

//对于每个key(ip),遍历所有的values(count),并累加

while(input.values.hasNext()) {

count += input.values.next();

}

//插入到大小为100的堆中

heap_insert(input.key, count);

在reduce结束的时候输出:

//输出当前reduce中count最高的100个ip

foreach( in dict) {

emit(ip, count);

}

由于reduce一般会有很多个,所以最后还需要将所有reduce的输出进行合并、再排序,并得到最终的前100个IP以及对应的访问量。

所以,使用Hadoop来做日志分析很显然不是一件简单事情,它带来了很多的额外的学习和运维成本,但是至少,它让超大规模的日志分析变成了可能。

怎样变得更简单

在超大规模的数据上做任何事情都不是一件容易的事情,包括日志分析,但也并不是说分布式的日志分析就一定要去写MapReduce代码,总是可以去做进一步的抽象,在特定的应用下让事情变得更简单。

也许有人会很自然的想到如果能用SQL来操作Hadoop上的数据该有多好。事实上,不仅仅只有你一个人会这么想,很多人都这么想,并且他们实现了这个想法,于是就有了Hive。

Hive现在也是Hadoop项目下面的一个子项目,它可以让我们用SQL的接口来执行MapReduce,甚至提供了JDBC和ODBC的接 口。有了这个之后,Hadoop基本上被包装成一个数据库。当然实际上Hive的SQL最终还是被翻译成了MapReduce代码来执行,因此即使最简单 的SQL可能也要执行好几十秒。幸好在通常的离线日志分析中,这个时间还是可以接受的。更重要的是,对于上面提到的例子,我们又可以用一样的SQL来完成 分析任务了。

当然Hive并不是完全的兼容SQL语法,而且也不能做到完全的对用户屏蔽细节。很多时候为了执行性能的优化,依然需要用户去了解一些MapReduce的基本知识,根据自己的应用模式来设置一些参数,否则我们可能会发现一个查询执行很慢,或者压根执行不出来。

另外,很显然Hive也并不能覆盖所有的需求,所以它依然保留插入原始MapReduce代码的接口,以便扩展。

更多的问题

即使有了Hive这样一个类似于数据库的东西,我们依然还有很多事情需要做。例如时间久了,可能会有越来越多的需要例行执行的SQL,而这些 SQL中,也许有一些是做了重复的事情;也许有一些的执行效率非常低下,一个复杂的SQL就占满了所有的计算资源。这样的系统会变得越来越难以维护的,直 到有一天例行的SQL终于跑不完了。而最终用户往往不会去关心这些事情,他们只关心自己提交的查询是不是能即时得到响应,怎么样才能尽快的拿到结果。

举个简单的例子,如果发现在使用apache_log的所有查询中,几乎没有人用其中的user_agent字段,那么我们完全可以把这个字段去除掉,或者拆分成两张表,以减少多数查询的IO时间,提高执行的效率。

为了系统化的解决这些问题,我们可能需要引入例行任务的调度机制,可能需要去分析所有的SQL来发现哪些是可以合并的、哪些的性能需要优化,使 用的数据表是不是需要做水平或者垂直分表等等。根据实际情况的不同,这时事情可能是人工来完成,也可能是写程序来自动分析并调整。

再者随着日志类型、分析需求的不断增长。用户会越来越多的抱怨很难找到想要的数据在哪份日志里,或者跑的好好的查询因为日志格式的变化而突然不 能用了。另外上面提到的ETL过程也会变得复杂,简单的转换导入脚本很可能已经解决不了问题。这时候可能需要构建一个数据管理系统,或者干脆考虑建立一个 所谓的数据仓库。

总之,随着日志数据量、日志类型、用户数量、分析需求等等的不断增长,越来越多的问题会逐渐浮现出来,日志分析这件事情可能就不再像我们最初想的那么简单,会变得越来越有价值,也越来越有挑战。

[转载]Android在线开发工具 App Inventor

mikel阅读(1028)

[转载]Android在线开发工具 App Inventor – 神舟龙 – 博客园.

最近在博客园看到一篇报道关于一个人好像是别出心裁的用Android程序求婚,最后成功了,在留言部分看到很多园友说:好浪漫,好幸福;文章中提到的一个在线开发程序,叫做app invertor,于是在网上稍微看了一下,下班回到家之后马上下载,起先是用迅雷下载的,结果下载进度一点也不动,于是乎,翻墙用IE9 下载,下载了两次没有成功,原因可能是保存路径有问题,建议先保存到桌面,然后再安装,下载地址如下http://dl.google.com/dl/appinventor/installers/windows/appinventor_setup_installer_v_1_2.exe(建议翻墙);下载好之后安装就可以了,好像官方建议安装过程中的路径不要修改,以防在加载模拟器的时候找不到路径,当然你也可以自己定义路径,不过在使用模拟器的时候需要人工的输入模拟器的路径,以后就不会出现这种问题了,下面就可以进入按Android的在线编辑页面了,请在浏览器的地址栏中输入:http://appinventor.googlelabs.com/ 就可以看到了,先放图···

第一次进入是会出现下面的界面,请点击new,并填写相应的项目名称即可,我填写的是First

进入First项目,界面如下

整个界面简洁,横向的可以分为四个部分,分别为palette(字典意思是调色板,就是工具),viewer(指示器),components(组件),properties(属性);

Palette:为我们所有将要用到的控件

Viewer:为Android模拟器面板,可拖放控件至此

Components:Viewer中的空间都会在此显示其控件名称

Properties:当某个控件处于编辑状态时,显示其属性可编辑

下面建立我自己的第一个Demo

1.修改标题

2.拖放控件,修改属性

3.从本地上传文件

5.此时是图片正在上传图片,因为我们是在线编辑的,所以建议各位不要上传太大的图片

6.点击右上角的“Blocks Editor”按钮进入编辑界面,此时会显示正在下载,即从网站现在我们的程序,此时有可能会要求下载java6,点击下载即可,下载完成之后如果你的app inventor路径不是默认的,需要填写仿真器的路径

7.连接本人的android2.2手机效果如下

作者:神舟龙
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

[转载]ASP.NET MVC中页面中进行自定义文字截取

mikel阅读(914)

[转载]ASP.NET MVC中页面中进行自定义文字截取 – peter cheng – 博客园.

效果如下:

其实截取方法跟aspx页面中一样,不管是用C#还是js或者CSS都可以实现,

我在这里只是想记录在MVC中怎么用的两种方法:

方法一:

先新建一个类

然后编写以下方法:

public static class HtmlHelpers
{
public static string Truncate(this HtmlHelper helper, string input, int length)
{
if (input.Length &lt;= length)
{
return input;
}
else
{
return input.Substring(0, length) + "...";
}
}
}

在web.config中此处进行注册

添加以下信息:


最后就是在View页面中用了:

<%: Html.Truncate(item.Title, 25) %> (MVC2写法)

@Html.Truncate(item.Artist.Name, 25) (MVC3写法)

方法二(MVC3):

直接在View页面中:

@helper Truncate(string input, int length)
{
    if (input.Length <= length) {
        @input
    } else {
        @input.Substring(0, length)<text>...</text>
    }
}

然后调用这个方法:

@Truncate(item.Artist.Name, 25)

[转载]如何将List转换相应的Html(xsl动态转换)(二)

mikel阅读(1133)

[转载]如何将List转换相应的Html(xsl动态转换)(二) – JasenKin – 博客园.

紧跟着上一篇随笔,本文主要涉及到如何将xml与xsl动态转换成html,这个才是最关键的地方,所有的内容都是围绕这个主题来进行开展的。根据指定的xsl样式将List<T>转换相应的Html,相关的随笔如下:

(一)、将List<T>转换成DataTable

(二)、将Xml与Xsl动态转换成Html

(三)、设置以及控制Xsl的内容样式。

二、XslTransform的具体实现

XslTransform主要的职责为:将xml与xsl动态转换成html。其中,XslCompiledTransform 提供了很多方法可以进行相关的转换,但使用起来并不是十分方便,因此必须在该基础上来对目前的类进行相关封装以及提取。具体的代码如下:

1     public class XslTransform : IDisposable
2     {
3         public StringWriter StringWriter
4         {
5             get;
6             private set;
7         }
8
9         public StringReader XmlStringReader
10         {
11             get;
12             private set;
13         }
14
15         public StringReader XslStringReader
16         {
17             get;
18             private set;
19         }
20
21         public XslTransform()
22         {
23             this.StringWriter = new StringWriter();
24         }
25
26         public string Transfer(string xmlText, string xslText)
27         {
28             if (string.IsNullOrWhiteSpace(xmlText)
29                 || string.IsNullOrWhiteSpace(xslText))
30             {
31                 return string.Empty;
32             }
33             this.XmlStringReader = new StringReader(xmlText);
34             this.XslStringReader = new StringReader(xslText);
35
36             return TransferXmlAndXslToHtml();
37         }
38
39         private string TransferXmlAndXslToHtml()
40         {
41             try
42             {
43                 using (XmlTextWriter writer = new XmlTextWriter(this.StringWriter))
44                 {
45                     return ToHtml(writer);
46                 }
47             }
48             catch
49             {
50                 return string.Empty;
51             }
52         }
53
54         private string ToHtml(XmlTextWriter writer)
55         {
56             XslCompiledTransform xslTransform = new XslCompiledTransform();
57             xslTransform.Load(XmlReader.Create(this.XslStringReader));
58             xslTransform.Transform(XmlReader.Create(this.XmlStringReader), writer);
59
60             return this.StringWriter.ToString();
61         }
62
63         #region IDisposable 成员
64
65         public void Dispose()
66         {
67             this.Dispose(true);
68             GC.SuppressFinalize(this);
69         }
70
71         private void Dispose(bool disposing)
72         {
73             if (this.StringWriter != null)
74             {
75                 this.StringWriter.Dispose();
76             }
77             if (this.XslStringReader != null)
78             {
79                 this.XslStringReader.Dispose();
80             }
81             if (this.XmlStringReader != null)
82             {
83                 this.XmlStringReader.Dispose();
84             }
85         }
86
87         #endregion
88     }

XslTransform 类主要的方法为54-61行的代码,如下所示:

54         private string ToHtml(XmlTextWriter writer)
55         {
56             XslCompiledTransform xslTransform = new XslCompiledTransform();
57             xslTransform.Load(XmlReader.Create(this.XslStringReader));
58             xslTransform.Transform(XmlReader.Create(this.XmlStringReader), writer);
59
60             return this.StringWriter.ToString();
61         }

第57行加载XSL的样式文本,58行在原有基础上将XML转换成XmlTextWriter对象。其中XmlTextWriter在初始化时,StringWriter对象作为参数传递进去,如以下的43行代码:

43 using (XmlTextWriter writer = new XmlTextWriter(this.StringWriter))

因此直接返回this.StringWriter.ToString();就获取到了我们所需的Html了。

其次,XslTransform 类还有一个注意的要点:实现IDisposable接口主要是将用到的资源及时释放掉,避免造成其他影响。

三、Xsl文件的设置以及添加到资源文件中

(1)创建MapperInfoXslContent.xslt样式文件,内容如下(目前使用最简单的,不做任何处理的样式文件):

<!--?xml version="1.0" encoding="utf-8"?-->

demo
<table>
<tbody>
<tr>
<td>
<table style="border-collapse: collapse;" border="1px" cellspacing="0px" bordercolor="#000000">
<tbody>
<tr bgcolor="#9acd32">
<th width="80">Name</th>
<th width="80">Value</th>
<th width="80">Percent</th>
<th width="230">CreatedTime</th>
<th width="60">IsActive</th>
<th width="190">TargerUrl</th>
</tr>
<tr>
<td width="80" bgcolor="#ff00ff"></td>
<td width="80"></td>
<td width="80" bgcolor="#ff00ff"></td>
<td width="230"></td>
<td width="60" bgcolor="#ff00ff"></td>
<td width="190"></td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>

(2)然后再创建XslResource.resx资源文件,将MapperInfoXslContent.xslt样式文件添加到XslResource.resx资源文件中,如下图所示:

四、转换后的效果

经过转换后得到的Html显示效果如下(测试过程中可以以HTML格式来查看字符串):

五、相关的单元测试

示例的单元测试代码如下(仅做了一些最基础的测试,验证内容是否存在):

[TestMethod()]
public void TransferTest()
{
string xmlText = GetXmlText();
string xslText = XslResource.MapperInfoXslContent;
string htmlContent = string.Empty;
using (XslTransform xslTransform = new XslTransform())
{
htmlContent = xslTransform.Transfer(xmlText, xslText);
}

Assert.IsTrue(!string.IsNullOrWhiteSpace(htmlContent));
Assert.IsTrue(htmlContent.Contains("true"));
Assert.IsTrue(htmlContent.Contains("false"));

for (int index = 0; index &lt; 3; index++)
{
Assert.IsTrue(htmlContent.Contains(
string.Concat("MapperInfoIndex", index.ToString())));
Assert.IsTrue(htmlContent.Contains(
string.Format(@"www.codeplex.com?Id={0}", index)));
Assert.IsTrue(htmlContent.Contains(index.ToString()));
}
}

private string GetXmlText()
{
List entities = CreateMapperInfos(3);
DataTable dataTable = EntityMapper.ToDataTable(entities);
DataSet dataSet = new DataSet("DataSet");
dataSet.Tables.Add(dataTable);

return dataSet.GetXml();
}

private List CreateMapperInfos(int count)
{
List entities = new List();
for (int index = 0; index &lt; count; index++)
{
entities.Add(new MapperInfo()
{
Name = string.Concat("MapperInfoIndex", index.ToString()),
IsActive = (index % 2 == 0 ? true : false),
CreatedTime = DateTime.Now,
Value = index,
Percent = GetPercent(index),
TargetUrl = string.Format(@"www.codeplex.com?Id={0}", index)
});
}

return entities;
}

private decimal? GetPercent(int index)
{
if (index % 2 == 0)
{
return index;
}

return null;
}

六、总结

上面涉及的仅仅是其中的一种,代码应该是比较精简的。还有另外一种采用XPathNavigator的,也就是笛子说的:“如果使用 XmlWriter 或 XmlDocument,则可以避开这个问题。另外,XslCompiledTransform.Transform 方法重载了几个版本中,如果我没记错的话,最应优先使用的是xml数据源为 XPathNavigator 的版本。”。关于这种情况,可以通过XmlDocument来创建相关的XPathNavigator对象,即:XPathNavigator navigator = XmlDocument.DocumentElement.CreateNavigator(),这种版本的我也重写了一份,但是好像没有转换成功,因此 就采用这种模式了。下一篇主要涉及到XSL样式的设计以及相关的函数、模板的应用。

[转载]快速开发新浪微博的firefox插件(上)

mikel阅读(966)

[转载]快速开发新浪微博的firefox插件(上) – Fei He – 博客园.

在开发这个插件之前,自己对JavaScript的使用也就是web page中简单的操作dom,而对于firefox插件开发一无所知,OAuth连听都没有听过。所以对于我眼前要干得事情我有两个难点,第一就是 firefox的插件机制,第二就是了解OAuth。

firefox的插件机制

对于一个firefox插件来说,我们首先需要了解的它的组织结构。打开一个firefox插件工程,你一般会看这么几个元素:chrome文件夹,defaults文件夹,chrome.manifest, install.rdf。

我们先从install.rdf说起,相比从文件名你就明白了这个文件是要干什么的。没错,这个文件就是firefox插件的安装文件。


<!--?xml version="1.0"?-->
flashcard@gmail.com
0.7
2
flashcard
Post the selected word to Sina weibo.
https://feihe.cnblogs.com
chrome://flashcard/skin/icon.png

Fei He

{ec8030f7-c20a-464f-9b0e-13a3a9e97384}
3.0
4.0.*

里面也就是对于你的firefox插件的一些描述信 息,其中比较关键的两个<em:id>, 在根节点description下的<em:id>是你的firefox插件的id,也就是说这个东西必须唯一(至少在你的firefox所 有插件中唯一),另一个位于<em:targetApplication>的<Description>下 的<em:id>则是firefox的id,这个是不能修改的。再就是<em:minVersion> 和<em:maxVersion>,它们用来描述你的firefox插件对于firefox版本的兼容性。

接着我们来了解defaults,一句话defaults就是你的firefox插件的preferences的default设置。

对于一个firefox插件最核心的部分就 是chrome.manifest和chrome文件夹。chrome.manifest有点像.NET的project文件,基本上就是对于整个 firefox插件所有元素的位置信息,而firefox本身就是通过这个这个manifest来定位具体的元素。那么一个firefox插件会包含那些 元素呢?打开chrome.manifest你就一目了然了。

overlay		chrome://browser/content/browser.xul    chrome://flashcard/content/overlay.xul
content		flashcard	chrome/content/flashcard/
skin	flashcard	classic	chrome/skin/classic/flashcard/

locale	flashcard	en-US	chrome/locale/flashcard/en-US/
style	chrome://global/content/customizeToolbar.xul	chrome://flashcard/skin/skin.css

这里面的结构基本都是行结构的,每一个行的头就是具体的firefox插件元素名称,而后面的是告诉firefox去那个位置查找这个元素。而这其中包含了这么几个元素:

  • overlay: 指向你的firefox插件的一个UI元素,包括contextmenu,toolbar,navigator bar之类。在上面的manifest中你看我这里指向了一个后缀名是xul的文件,其实它的全称是Xml User Interface。顾名思义就是使用xml的格式来描述UI。
<!--?xml version="1.0"?-->
<!--?xml-stylesheet href="chrome://flashcard/skin/skin.css" type="text/css"?-->

<script type="application/x-javascript">// <!&#91;CDATA&#91;
     mce:0
// &#93;&#93;></script>
<script type="application/x-javascript">// <!&#91;CDATA&#91;
     mce:1
// &#93;&#93;></script>
<script type="application/x-javascript">// <!&#91;CDATA&#91;
     mce:2
// &#93;&#93;></script>
<script type="application/x-javascript">// <!&#91;CDATA&#91;
     mce:3
// &#93;&#93;></script>

<script type="application/x-javascript">// <!&#91;CDATA&#91;
     mce:4
// &#93;&#93;></script>
<script type="application/x-javascript">// <!&#91;CDATA&#91;
     mce:5
// &#93;&#93;></script>
<script type="application/x-javascript">// <!&#91;CDATA&#91;
     mce:6
// &#93;&#93;></script>

上面是我用的一个overlay.xul, 我这里是给firefox的contextmenu加了一个新的menuitem,并使用separator和原有的menuitems分隔起来。这里的 文件名是可以随意取的,那是你起的名字必须在chrome.manifest中应用。到这里很多人好奇,那么你加的menuitem相应的行为在那里呢? 细心的你也许发现我这个xul中引用了一些JavaScript,而对于我们menuitem,firefox提供了2中方法去关联行为:第一种就是在 control的oncommand中直接指定control的行为;第二中是JavaScript中使用 document.getElementByID来获取control从而绑定行为:


document.getElementById("menuitem_flashcard_add").addEventListener("click", function(event){}, false);

并且,我也在这个文件中指定了css文件。其实对于xul文件中javascript和css的使用和html都基本一致。

  • content: 就是你的firefox插件的核心,包括javascript脚本和XUL
  • skin:即使皮肤,你可以在给你的插件做不同的皮肤,我的mainifest中指定了我使用classic的皮肤,所以我在skin文件夹下就应classic的文件夹来对应。
  • locale:国际化,对于我们firefox插件中需要需要国家化的UI control, 我们可以使用它的label属性,同时在chrome.manifest中指定的culture文件夹下定义dtd文件来对应,例如: overlay.xul中的control定义:

dtd文件的定义:

<!--ENTITY flashcard.menuitem.label "Post to flashcard"-->
  • 它们之间使用control的label属性关联,而overlay.xul具体和chrome.manifest指定culture文件夹下的那个dtd文件关联,你可以看到在我的overlay.xul中有这么一句定义:
  • style: 也就是overlay的一些样式,比如css。
  • 它们之间使用control的label属性关联,而overlay.xul具体和chrome.manifest指定culture文件夹下的那个dtd文件关联,你可以看到在我的overlay.xul中有这么一句定义:
  • style: 也就是overlay的一些样式,比如css。

你的firefox插件有了UI,也有了相 应的行为和样式,那么你还需要什么呢?需要存储,也就是你需要存储一些preferences信息或者其他的比如我这里我需要存储新浪微博中用户授权通过 之后获得的Oauth_token的相关信息。firefox对于存储提供了很多方式,你可文件存贮在特殊位置,或者使用SQLite这种肖的文件数据 库。另外一种最简单的也就是我采用的就是preferences的存贮。对于firefox插件,你可以在你的install.rdf中注 明你的preference文件,这样你可以让用户使用的preference文件做一些设置,并保存。而我这里我指希望使用preferences来存 贮,所以我并不希望用户看到它,那么我就不需要在install.rdf中注明。

preference文件也是一个xul文件,所以你也可以应用javascript和css,来对于你的preference中的control进行行为的绑定和样式的渲染。我这里的preference如下:

<!--?xml version="1.0"?-->
<!--?xml-stylesheet href="chrome://global/skin/" type="text/css"?-->

而这其中的preferences节点中的内容便是用来做preference存贮的,你可以像我一样通过

Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefService).getBranch("Sina.WeiBo.")

来获得所有name前缀为Sian.Weibo的preference,然后调用它的 getCharPref(‘oauth.access_token’)来获取值,或者通过 setCharPref(‘oauth.access_token’)设置值,对于preference,MDN上有详细的API介绍。对于在 preference中引用javascript比较tricky的一点就是如果在你preference中使用prePanel,那么 javascript的引用代码一定要在prePanel后面,否则你的prePanel就什么都看不到了。

最后一点,有些时候也许你希望你的firefox插件在完成某些行为之后给用户一个notification,在firefox3中你可以使用普通 的notification或者alert,而在firefox4中你可以使用popupNotification,效果非常炫,而且还可以指定图片和相 应的action,使得用户在得到这个notification之后可以做进一步的行为。示例如下:

PopupNotifications.show(gBrowser.selectedBrowser, "flashcard-add",
        '"'+ selectedWord +'" 已经成功加入你的单词本',
        null, 
		{
			label: "确定",
			accessKey: "D",
			callback: function() {
			}	
		},
		[
			{
				label: "Reset",
				accessKey: "R",
				callback: function() {
					Browser.Preferences.clearUserPref("oauth.access_token");
					Browser.Preferences.clearUserPref("oauth.access_token_secret");
				}	
			},
		]);

而指定图片则要在css中

.popup-notification-icon[popupid="flashcard-add"] {
	list-style-image: url("chrome://flashcard/skin/icon.png");
}

这里是我在快速开发一个firefox插件中获得知识,如果你希望更详细的知识还是需要参考MDN。写到这里发现篇幅有点长,还是决定分为上,下两篇。下篇来讲Sina WeiBo的Oauth授权机制。

[转载]eclipse 最全快捷键 分享快乐与便捷

mikel阅读(576)

[转载]eclipse 最全快捷键 分享快乐与便捷 – 耿玉龙 – 博客园.

Ctrl+1 快速修复(最经典的快捷键,就不用多说了)
Ctrl+D: 删除当前行
Ctrl+Alt+↓ 复制当前行到下一行(复制增加)
Ctrl+Alt+↑ 复制当前行到上一行(复制增加)
Alt+↓ 当前行和下面一行交互位置(特别实用,可以省去先剪切,再粘贴了)
Alt+↑ 当前行和上面一行交互位置(同上)
Alt+← 前一个编辑的页面
Alt+→ 下一个编辑的页面(当然是针对上面那条来说了)
Alt+Enter 显示当前选择资源(工程,or 文件 or文件)的属性
Shift+Enter 在当前行的下一行插入空行(这时鼠标可以在当前行的任一位置,不一定是最后)
Shift+Ctrl+Enter 在当前行插入空行(原理同上条)
Ctrl+Q 定位到最后编辑的地方
Ctrl+L 定位在某行 (对于程序超过100的人就有福音了)
Ctrl+M 最大化当前的Edit或View (再按则反之)
Ctrl+/ 注释当前行,再按则取消注释
Ctrl+O 快速显示 OutLine
Ctrl+T 快速显示当前类的继承结构
Ctrl+W 关闭当前Editer
Ctrl+K 参照选中的Word快速定位到下一个
Ctrl+E 快速显示当前Editer的下拉列表(如果当前页面没有显示的用黑体表示)
Ctrl+/(小键盘) 折叠当前类中的所有代码
Ctrl+×(小键盘) 展开当前类中的所有代码
Ctrl+Space 代码助手完成一些代码的插入(但一般和输入法有冲突,可以修改输入法的热键,也可以暂用

Alt+/来代替)
Ctrl+Shift+E 显示管理当前打开的所有的View的管理器(可以选择关闭,激活等操作)
Ctrl+J 正向增量查找(按下Ctrl+J后,你所输入的每个字母编辑器都提供快速匹配定位到某个单词,如果没

有,则在stutes line中显示没有找到了,查一个单词时,特别实用,这个功能Idea两年前就有了)
Ctrl+Shift+J 反向增量查找(和上条相同,只不过是从后往前查)
Ctrl+Shift+F4 关闭所有打开的Editer
Ctrl+Shift+X 把当前选中的文本全部变味小写
Ctrl+Shift+Y 把当前选中的文本全部变为小写
Ctrl+Shift+F 格式化当前代码
Ctrl+Shift+P 定位到对于的匹配符(譬如{}) (从前面定位后面时,光标要在匹配符里面,后面到前面,则反

之)
下面的快捷键是重构里面常用的,本人就自己喜欢且常用的整理一下(注:一般重构的快捷键都是Alt+Shift

开头的了)
Alt+Shift+R 重命名 (是我自己最爱用的一个了,尤其是变量和类的Rename,比手工方法能节省很多劳动力

)
Alt+Shift+M 抽取方法 (这是重构里面最常用的方法之一了,尤其是对一大堆泥团代码有用)
Alt+Shift+C 修改函数结构(比较实用,有N个函数调用了这个方法,修改一次搞定)
Alt+Shift+L 抽取本地变量( 可以直接把一些魔法数字和字符串抽取成一个变量,尤其是多处调用的时候)
Alt+Shift+F 把Class中的local变量变为field变量 (比较实用的功能)
Alt+Shift+I 合并变量(可能这样说有点不妥Inline)
Alt+Shift+V 移动函数和变量(不怎么常用)
Alt+Shift+Z 重构的后悔药(Undo)
编辑
作用域 功能 快捷键
全局 查找并替换 Ctrl+F
文本编辑器 查找上一个 Ctrl+Shift+K
文本编辑器 查找下一个 Ctrl+K
全局 撤销 Ctrl+Z
全局 复制 Ctrl+C
全局 恢复上一个选择 Alt+Shift+↓
全局 剪切 Ctrl+X
全局 快速修正 Ctrl1+1
全局 内容辅助 Alt+/
全局 全部选中 Ctrl+A
全局 删除 Delete
全局 上下文信息 Alt+?
Alt+Shift+?
Ctrl+Shift+Space
java编辑器 显示工具提示描述 F2
java编辑器 选择封装元素 Alt+Shift+↑
java编辑器 选择上一个元素 Alt+Shift+←
java编辑器 选择下一个元素 Alt+Shift+→
文本编辑器 增量查找 Ctrl+J
文本编辑器 增量逆向查找 Ctrl+Shift+J
全局 粘贴 Ctrl+V
全局 重做 Ctrl+Y

查看
作用域 功能 快捷键
全局 放大 Ctrl+=
全局 缩小 Ctrl+-

窗口
作用域 功能 快捷键
全局 激活编辑器 F12
全局 切换编辑器 Ctrl+Shift+W
全局 上一个编辑器 Ctrl+Shift+F6
全局 上一个视图 Ctrl+Shift+F7
全局 上一个透视图 Ctrl+Shift+F8
全局 下一个编辑器 Ctrl+F6
全局 下一个视图 Ctrl+F7
全局 下一个透视图 Ctrl+F8
文本编辑器 显示标尺上下文菜单 Ctrl+W
全局 显示视图菜单 Ctrl+F10
全局 显示系统菜单 Alt+-

导航
作用域 功能 快捷键
java编辑器 打开结构 Ctrl+F3
全局 打开类型 Ctrl+Shift+T
全局 打开类型层次结构 F4
全局 打开声明 F3
全局 打开外部javadoc Shift+F2
全局 打开资源 Ctrl+Shift+R
全局 后退历史记录 Alt+←
全局 前进历史记录 Alt+→
全局 上一个 Ctrl+,
全局 下一个 Ctrl+.
java编辑器 显示大纲 Ctrl+O
全局 在层次结构中打开类型 Ctrl+Shift+H
全局 转至匹配的括号 Ctrl+Shift+P
全局 转至上一个编辑位置 Ctrl+Q
java编辑器 转至上一个成员 Ctrl+Shift+↑
java编辑器 转至下一个成员 Ctrl+Shift+↓
文本编辑器 转至行 Ctrl+L

搜索
作用域 功能 快捷键
全局 出现在文件中 Ctrl+Shift+U
全局 打开搜索对话框 Ctrl+H
全局 工作区中的声明 Ctrl+G
全局 工作区中的引用 Ctrl+Shift+G

文本编辑
作用域 功能 快捷键
文本编辑器 改写切换 Insert
文本编辑器 上滚行 Ctrl+↑
文本编辑器 下滚行 Ctrl+↓

文件
作用域 功能 快捷键
全局 保存 Ctrl+X
Ctrl+S
全局 打印 Ctrl+P
全局 关闭 Ctrl+F4
全局 全部保存 Ctrl+Shift+S
全局 全部关闭 Ctrl+Shift+F4
全局 属性 Alt+Enter
全局 新建 Ctrl+N

项目
作用域 功能 快捷键
全局 全部构建 Ctrl+B

源代码
作用域 功能 快捷键
java编辑器 格式化 Ctrl+Shift+F
java编辑器 取消注释 Ctrl+\
java编辑器 注释 Ctrl+/
java编辑器 添加导入 Ctrl+Shift+M
java编辑器 组织导入 Ctrl+Shift+O
java编辑器 使用try/catch块来包围 未设置,太常用了,所以在这里列出,建议自己设置。
也可以使用Ctrl+1自动修正。

运行
作用域 功能 快捷键
全局 单步返回 F7
全局 单步跳过 F6
全局 单步跳入 F5
全局 单步跳入选择 Ctrl+F5
全局 调试上次启动 F11
全局 继续 F8
全局 使用过滤器单步执行 Shift+F5
全局 添加/去除断点 Ctrl+Shift+B
全局 显示 Ctrl+D
全局 运行上次启动 Ctrl+F11
全局 运行至行 Ctrl+R
全局 执行 Ctrl+U

重构
作用域 功能 快捷键
全局 撤销重构 Alt+Shift+Z
全局 抽取方法 Alt+Shift+M
全局 抽取局部变量 Alt+Shift+L
全局 内联 Alt+Shift+I
全局 移动 Alt+Shift+V
全局 重命名 Alt+Shift+R
全局 重做 Alt+Shift+Y
Ctrl+1 快速修复(最经典的快捷键,就不用多说了)
Ctrl+D: 删除当前行
Ctrl+Alt+↓ 复制当前行到下一行(复制增加)
Ctrl+Alt+↑ 复制当前行到上一行(复制增加)
Alt+↓ 当前行和下面一行交互位置(特别实用,可以省去先剪切,再粘贴了)
Alt+↑ 当前行和上面一行交互位置(同上)
Alt+← 前一个编辑的页面
Alt+→ 下一个编辑的页面(当然是针对上面那条来说了)
Alt+Enter 显示当前选择资源(工程,or 文件 or文件)的属性
Shift+Enter 在当前行的下一行插入空行(这时鼠标可以在当前行的任一位置,不一定是最后)
Shift+Ctrl+Enter 在当前行插入空行(原理同上条)
Ctrl+Q 定位到最后编辑的地方
Ctrl+L 定位在某行 (对于程序超过100的人就有福音了)
Ctrl+M 最大化当前的Edit或View (再按则反之)
Ctrl+/ 注释当前行,再按则取消注释
Ctrl+O 快速显示 OutLine
Ctrl+T 快速显示当前类的继承结构
Ctrl+W 关闭当前Editer
Ctrl+K 参照选中的Word快速定位到下一个
Ctrl+E 快速显示当前Editer的下拉列表(如果当前页面没有显示的用黑体表示)
Ctrl+/(小键盘) 折叠当前类中的所有代码
Ctrl+×(小键盘) 展开当前类中的所有代码
Ctrl+Space 代码助手完成一些代码的插入(但一般和输入法有冲突,可以修改输入法的热键,也可以暂用

Alt+/来代替)
Ctrl+Shift+E 显示管理当前打开的所有的View的管理器(可以选择关闭,激活等操作)
Ctrl+J 正向增量查找(按下Ctrl+J后,你所输入的每个字母编辑器都提供快速匹配定位到某个单词,如果没

有,则在stutes line中显示没有找到了,查一个单词时,特别实用,这个功能Idea两年前就有了)
Ctrl+Shift+J 反向增量查找(和上条相同,只不过是从后往前查)
Ctrl+Shift+F4 关闭所有打开的Editer
Ctrl+Shift+X 把当前选中的文本全部变味小写
Ctrl+Shift+Y 把当前选中的文本全部变为小写
Ctrl+Shift+F 格式化当前代码
Ctrl+Shift+P 定位到对于的匹配符(譬如{}) (从前面定位后面时,光标要在匹配符里面,后面到前面,则反

之)
下面的快捷键是重构里面常用的,本人就自己喜欢且常用的整理一下(注:一般重构的快捷键都是Alt+Shift

开头的了)
Alt+Shift+R 重命名 (是我自己最爱用的一个了,尤其是变量和类的Rename,比手工方法能节省很多劳动力

)
Alt+Shift+M 抽取方法 (这是重构里面最常用的方法之一了,尤其是对一大堆泥团代码有用)
Alt+Shift+C 修改函数结构(比较实用,有N个函数调用了这个方法,修改一次搞定)
Alt+Shift+L 抽取本地变量( 可以直接把一些魔法数字和字符串抽取成一个变量,尤其是多处调用的时候)
Alt+Shift+F 把Class中的local变量变为field变量 (比较实用的功能)
Alt+Shift+I 合并变量(可能这样说有点不妥Inline)
Alt+Shift+V 移动函数和变量(不怎么常用)
Alt+Shift+Z 重构的后悔药(Undo)
编辑
作用域 功能 快捷键
全局 查找并替换 Ctrl+F
文本编辑器 查找上一个 Ctrl+Shift+K
文本编辑器 查找下一个 Ctrl+K
全局 撤销 Ctrl+Z
全局 复制 Ctrl+C
全局 恢复上一个选择 Alt+Shift+↓
全局 剪切 Ctrl+X
全局 快速修正 Ctrl1+1
全局 内容辅助 Alt+/
全局 全部选中 Ctrl+A
全局 删除 Delete
全局 上下文信息 Alt+?
Alt+Shift+?
Ctrl+Shift+Space
java编辑器 显示工具提示描述 F2
java编辑器 选择封装元素 Alt+Shift+↑
java编辑器 选择上一个元素 Alt+Shift+←
java编辑器 选择下一个元素 Alt+Shift+→
文本编辑器 增量查找 Ctrl+J
文本编辑器 增量逆向查找 Ctrl+Shift+J
全局 粘贴 Ctrl+V
全局 重做 Ctrl+Y

查看
作用域 功能 快捷键
全局 放大 Ctrl+=
全局 缩小 Ctrl+-

窗口
作用域 功能 快捷键
全局 激活编辑器 F12
全局 切换编辑器 Ctrl+Shift+W
全局 上一个编辑器 Ctrl+Shift+F6
全局 上一个视图 Ctrl+Shift+F7
全局 上一个透视图 Ctrl+Shift+F8
全局 下一个编辑器 Ctrl+F6
全局 下一个视图 Ctrl+F7
全局 下一个透视图 Ctrl+F8
文本编辑器 显示标尺上下文菜单 Ctrl+W
全局 显示视图菜单 Ctrl+F10
全局 显示系统菜单 Alt+-

导航
作用域 功能 快捷键
java编辑器 打开结构 Ctrl+F3
全局 打开类型 Ctrl+Shift+T
全局 打开类型层次结构 F4
全局 打开声明 F3
全局 打开外部javadoc Shift+F2
全局 打开资源 Ctrl+Shift+R
全局 后退历史记录 Alt+←
全局 前进历史记录 Alt+→
全局 上一个 Ctrl+,
全局 下一个 Ctrl+.
java编辑器 显示大纲 Ctrl+O
全局 在层次结构中打开类型 Ctrl+Shift+H
全局 转至匹配的括号 Ctrl+Shift+P
全局 转至上一个编辑位置 Ctrl+Q
java编辑器 转至上一个成员 Ctrl+Shift+↑
java编辑器 转至下一个成员 Ctrl+Shift+↓
文本编辑器 转至行 Ctrl+L

搜索
作用域 功能 快捷键
全局 出现在文件中 Ctrl+Shift+U
全局 打开搜索对话框 Ctrl+H
全局 工作区中的声明 Ctrl+G
全局 工作区中的引用 Ctrl+Shift+G

文本编辑
作用域 功能 快捷键
文本编辑器 改写切换 Insert
文本编辑器 上滚行 Ctrl+↑
文本编辑器 下滚行 Ctrl+↓

文件
作用域 功能 快捷键
全局 保存 Ctrl+X
Ctrl+S
全局 打印 Ctrl+P
全局 关闭 Ctrl+F4
全局 全部保存 Ctrl+Shift+S
全局 全部关闭 Ctrl+Shift+F4
全局 属性 Alt+Enter
全局 新建 Ctrl+N

项目
作用域 功能 快捷键
全局 全部构建 Ctrl+B

源代码
作用域 功能 快捷键
java编辑器 格式化 Ctrl+Shift+F
java编辑器 取消注释 Ctrl+\
java编辑器 注释 Ctrl+/
java编辑器 添加导入 Ctrl+Shift+M
java编辑器 组织导入 Ctrl+Shift+O
java编辑器 使用try/catch块来包围 未设置,太常用了,所以在这里列出,建议自己设置。
也可以使用Ctrl+1自动修正。

运行
作用域 功能 快捷键
全局 单步返回 F7
全局 单步跳过 F6
全局 单步跳入 F5
全局 单步跳入选择 Ctrl+F5
全局 调试上次启动 F11
全局 继续 F8
全局 使用过滤器单步执行 Shift+F5
全局 添加/去除断点 Ctrl+Shift+B
全局 显示 Ctrl+D
全局 运行上次启动 Ctrl+F11
全局 运行至行 Ctrl+R
全局 执行 Ctrl+U

重构
作用域 功能 快捷键
全局 撤销重构 Alt+Shift+Z
全局 抽取方法 Alt+Shift+M
全局 抽取局部变量 Alt+Shift+L
全局 内联 Alt+Shift+I
全局 移动 Alt+Shift+V
全局 重命名 Alt+Shift+R
全局 重做 Alt+Shift+Y

[转载]程序员养生(01)心态

mikel阅读(687)

[转载]程序员养生(01) -- 心态 – zhuweisky – 博客园.

在程序之外,是程序员的生活。

当我们刚刚告别校园成为一个程序员时,大都拥有成功的梦想、万分的激情,那时的我们也拥有精力充沛的健康身体。 随时间流逝,5年过去了、10年过去了,也许,梦想可能渐渐暗淡,激情慢慢消退。但,有一点是肯定的,我们的身体大不如前了,像视力下降、慢性胃炎、颈椎 病、失眠、神经衰弱等等接踵而来,这些病症几乎成了我们这个行业的职业病。

从健康的角度来说,程序员这个职业,有几个非常不利的因素:

第一,程序员需要专注。程序员经常连续长时间地(例如连续8个小时以上,为解决一个bug,饭顾不上吃、睡觉也在想解决方案)专注在一个问题上,这对气血的消耗是非常巨大的。几年前华为一个员工因连续加班而导致过劳死,就是一个典型的例子。

第二,长时间静坐。长时间静坐,导致身体气血循环不畅、经常有某个部分涨痛的情况出现,这就提醒你要多运动运动了。而且,久坐伤胃,过度思虑也伤胃,所以很多程序员都有慢性胃炎这类疾病。

第三,脑力消耗巨大。靠出卖脑力养家活口的程序员,连续的脑力消耗、加上工作方面的精神压力巨大,久而久之,容易患上头痛、偏头痛等毛病。

第四,长时间面对电脑。虽说现在都用LCD显示器,辐射小一些,但是长时间专注地盯着屏幕,对视力的危害是非常大的。而且,久视伤肝,加上经常晚上熬夜加班,程序员就容易肝火旺、眼眶痛(特别是鱼腰穴处)、目赤等。

身体是自己的,是一辈子的事情。我向来不赞成为了事业,而牺牲健康。(还有,为了利益,而牺牲感情;为了金钱,而不择手段。)

想要健康的身体和健康的生活,心态是最重要的。而且,实际上,在诸多的因素中,心态对身体健康的影响是最大的。中医早在几千年前就深刻地认识到了这一点,长期的沉侵在过度的七情(怒喜忧惊悲思恐)之中,对身体的损害相当之大。就正如久郁成疾一样。

随着年纪的增长,心态会慢慢发生变化。以前觉得很重要的,像金钱、名利、地位,慢慢地发现它不是那么重要;以前不以为然的,像亲情、友情,却觉得越来越珍贵。

今天,已而立之年。就像大多数人一样,不太成功,也不太失败。平淡真实地过着每一天,也许这就是一种幸福的状态的吧。下面就罗列一些我自以为是的观点,仅供大家参考。

(1)不强求、顺其自然。不强求于人,不要让别人难做;也不要强求于事,谋事在人、成事在天。

我们很多痛苦的根源在于,我们太执着了,太强求了。即使有雄心壮志,要做一番大事业,也该是尽人事,听天命。这不是宿命论,而是诸多事情,人算不如天算,塞翁失马焉知非福呢?

(2)掌握事物的规律,抓住关键点,就不用紧张、焦虑,而且往往事半功倍。

比如,我们没有必要不等春天的到来而焦急地在冬天的时候去播种(而现实中,我们为了急于求成,常常在不合时机的时候做不适合的事),因为这违反了自然界的 规律,付出一定没有回报。反过来,你也不能因一时懒惰而错过了春天播种、秋天收获的时节,否则,因一时情绪之快,你就要多等一年了。

很多事情,看似无为,实则大为。正像老子说的,无为而无不为。

(3)勤动脑体,不动心。

正常的工作、生活是没问题的(即勤动脑体),但是不要动心。“动心”的意思是说,一件事情,你放不下,吃饭的时候也想、睡觉的时候也想,时时刻刻挂在心上,这就是动心了。动心会使气郁,会伤身。

(4)要放得下、要看得开、要放得开。知足常乐。

放得下是魄力、看的开是胸襟、放得开是气度。知足则是最大的精神财富。

(5)失意时要坚韧,得意时要低调。

人生在世,难免有得有失,难免有低潮和春风得意之时。就像,舍得舍得,舍去之后便是得;而得失得失,跟在得后面的就是失。了解这一点,无论是在低潮还是在高潮,我们的情绪都不会太激烈。平淡一点、活得从容。

路是我们自己选的,拥有一种良好的心态,其实,生活就在我们自己的手中。

[转载]如何将List转换相应的Html(xsl动态转换)(一)

mikel阅读(1033)

[转载]如何将List转换相应的Html(xsl动态转换)(一) – JasenKin – 博客园.

一、前言

根据指定的xsl样式将List<T>转换相应的Html,其中涉及到怎样将List<T>转换成DataTable,如何将xml文本、xsl样式文本动态转换成html以及如何设置以及控制xsl样式。主要步骤如下:

步骤一、将List<T>转换成DataTable。

步骤二、将Xml与Xsl动态转换成Html。

步骤三、设置以及控制Xsl的内容样式。

以上的三个步骤本人将以此顺序介绍相关的内容,分别对应相关的随笔,因为本人上班的时候不能上网以及时间上的问题,所以才将该文章分3次来写。

二、类图设计

以上的内容涉及的类图虽然很简单,但是本人还是花了不少时间的来实现具体功能,代码质量还是可以保证的。EntityMapper负责将 List<T>转换成DataTable(目前先将就着用这个,还有一个比较复杂的,涉及的东西比较多,此处不会讲解,以后有时间再 写),XslTransform负责将xml文本、xsl文本转换成html,XslTransformFacade外观模式封装其中的细节,如下:

三、将List<T>转换成DataTable,再转换成xml的具体实现

这里主要是个思路的问题,先将List<T>转换成DataTable,然后将DataTable添加到DataSet中,最后通过 DataSet的GetXml()方法获取Xml内容。这里思路正确的话,实现不是很复杂。先看下XslTransformFacade类,基本思路都封 装在该类中:

public class XslTransformFacade
{
public static string ToHtml(List entities,string xslText) where T : new()
{
if (ValidateArgs(entities,xslText))
{
return string.Empty;
}

string xmlText= GetXmlText(entities);

using (XslTransform xslTransform = new XslTransform())
{
return xslTransform.Transfer(xmlText, xslText);
}
}

private static bool ValidateArgs(List entities, string xslText)
{
return entities == null || entities.Count == 0
|| string.IsNullOrWhiteSpace(xslText);
}

private static string GetXmlText(List entities) where T : new()
{
using (DataSet dataSet = new DataSet("DataSet"))
{
DataTable dataTable = EntityMapper.ToDataTable(entities);
dataSet.Tables.Add(dataTable);
return dataSet.GetXml();
}
}
}

这一步骤主要是通过GetXmlText(List entities)方法来实现的。EntityMapper.ToDataTable(entities)方法将在下面介绍。生成的Xml如下(示例):

-
-
MapperInfoIndex0
2011-05-24T00:27:23.734375+08:00
true
0

0   www.codeplex.com?Id=0

-
MapperInfoIndex1
2011-05-24T00:27:23.734375+08:00
false
1
www.codeplex.com?Id=1

-

其次第12-15行主要是将xmlText、xslText转换成html,这将在后续的文章中介绍具体实现:

using (XslTransform xslTransform = new XslTransform())
{
return xslTransform.Transfer(xmlText, xslText);
}

四、将List<T>转换成DataTable

这里主要是通过反射将List<T>转换成DataTable。其中需要设置DataTable的DataColumnCollection集合以及设置DataRowCollection集合。具体代码如下:

public sealed class EntityMapper
{
public static DataTable ToDataTable(List entities) where T : new()
{
if (entities == null || entities.Count == 0)
{
return new DataTable();
}

using (DataTable dataTable = new DataTable(typeof(T).Name))
{
PropertyInfo[] properties = typeof(T).GetProperties();

SetColumnsType(properties, dataTable);
SetTableContent(entities, properties, dataTable);

return dataTable;
}
}

private static void SetTableContent(List entities,
PropertyInfo[] properties, DataTable dataTable)
{
foreach (T entity in entities)
{
AddTableRowsAndContent(properties, entity,dataTable);
}
}

private static void AddTableRowsAndContent(PropertyInfo[] properties,
T entity, DataTable dataTable)
{
DataRow newRow = dataTable.NewRow();
foreach (PropertyInfo propertyInfo in properties)
{
if (!CanGetPropertyValue(propertyInfo,dataTable))
{
continue;
}

try
{
object objValue = propertyInfo.GetValue(entity, null);
newRow[propertyInfo.Name] = objValue ?? DBNull.Value;
}
finally
{
}
}

dataTable.Rows.Add(newRow);
}

private static bool CanGetPropertyValue(PropertyInfo propertyInfo, DataTable dataTable)
{
return propertyInfo.CanRead &amp;&amp;
dataTable.Columns.Contains(propertyInfo.Name);
}

private static void SetColumnsType(PropertyInfo[] properties, DataTable dataTable)
{
Type colType = null;

foreach (PropertyInfo propInfo in properties)
{
if (propInfo.PropertyType.IsGenericType)
{
colType = Nullable.GetUnderlyingType(propInfo.PropertyType);
}
else
{
colType = propInfo.PropertyType;
}

if (colType.FullName.StartsWith("System"))
{
dataTable.Columns.Add(propInfo.Name, colType);
}
}
}
}

这里主要的操作步骤为以下2行代码:

14 SetColumnsType(properties, dataTable);
15 SetTableContent(entities, properties, dataTable);

14行设置列的类型,15行设置DataRowCollection的DataRow内容,对于上面的代码,再多的解释都是无用的,看具体代码就行了。

其中需要解释一下的就是54-58行:

54 private static bool CanGetPropertyValue(PropertyInfo propertyInfo, DataTable dataTable)
55 {
56 return propertyInfo.CanRead &&
57 dataTable.Columns.Contains(propertyInfo.Name);
58 }
因为当属性不可读,并且DataColumnCollection不包行该属性名时,赋值可能会抛出异常的。

其次还提一下第10行:

10 using (DataTable dataTable = new DataTable(typeof(T).Name))

这里用using来释放资源,主要是使代码中不存在任何警告,警告有时候使系统奔溃也有可能。否则进行代码分析的时候会出现警告信息,如下图所示:

五、DataTable 转换成List<T> (这个是附加的,与此主题无关,但是也是EntityMapper 的一部分)

虽然以前写了一篇《 将DataRow转换成相应的对象(通用以及泛型操作) 》 ,但是并不是将DataTable 转换成List<T>,后续也有些地方进行了改进,代码如下:

public class EntityMapperTest
{
[TestMethod()]
public void ToDataTableTest()
{
List entities = CreateMapperInfos(9);
DataTable result = EntityMapper.ToDataTable(entities);
Assert.IsNotNull(result);
Assert.IsNotNull(result.Rows);
Assert.AreEqual(9, result.Rows.Count);
int index = 0;
foreach (DataRow dataRow in result.Rows)
{
Assert.AreEqual(dataRow[“Name”],
string.Concat(“MapperInfoIndex”, index.ToString()));
Assert.AreEqual(dataRow[“IsActive”], index % 2 == 0 ? true : false);
Assert.AreEqual(dataRow[“Value”], index);
Assert.IsNotNull(dataRow[“CreatedTime”]);
Assert.AreEqual(dataRow[“Percent”], DBNull.Value);
index++;

}
}

private List CreateMapperInfos(int count)
{
List entities = new List();
for (int index = 0; index < count; index++) { entities.Add(new MapperInfo() { Name = string.Concat("MapperInfoIndex", index.ToString()), IsActive = (index % 2 == 0 ? true : false), CreatedTime = DateTime.Now, Value = index }); } return entities; } } [/csharp] 七、总结 最近二个多月,忙死我了。这段时间转SIT测试了,终于又可以轻松一阵了,哈哈。这些随笔的内容都是上班时间之外写的,每次写的代码都做单元测试,主要是避免出现显而易见的BUG,以及将代码积累并且更新到自己的框架中。接下来的一篇主要是如何将xml文本、xsl文本动态转换成html,这个花费了本人一段时间,一直在摸索才整理出来的,主要是通过XslCompiledTransform.Transform(XmlReader input, XmlWriter results)来实现的,本人已经更新了几个版本了,这个应该是最终版本的,同时也是最精简的版本。