[JQuery]仿google 的输入提示框JS类下载(jQuery plugin: Autocom

mikel阅读(752)

JQuery plugin: Autocomplete

Autocomplete an input field to enable users quickly finding and selecting some value, leveraging searching and filtering.

By giving an autocompleted field focus or entering something into it, the plugin starts searching for matching entries and displays a list of values to choose from. By entering more characters, the user can filter down the list to better matches.

This can be used to enter previous selected values, eg. for tags, to complete an address, eg. enter a city name and get the zip code, or maybe enter email addresses from an addressbook.

Current version: 1.0.2
Compressed filesize: 7596 bytes
License: MIT/GPL
Tested in: Firefox 2, IE 6 & 7, Opera 9, Safari 3

Files:

Download
Changelog
Demos
Documentation (Plugin Options)

Dependencies

Required

Optional

  • optional: bgiframe plugin to fix select-problems in IE, just include to apply to autocomplete

Support

  • Please post questions to the jQuery discussion list, putting [autocomplete] into the subject of your post, making it easier to spot it and respond quickly. Keep your question short and succinct and provide code when possible; a testpage makes it much more likely that you get an useful answer in no time.
  • Please post bug reports and other contributions (enhancements, features) to the jQuery bug tracker (requires registration). Please put [autocomplete] into the title of a ticket.

JQuery plugin: Autocomplete

Autocomplete an input field to enable users quickly finding and selecting some value, leveraging searching and filtering.

By giving an autocompleted field focus or entering something into it, the plugin starts searching for matching entries and displays a list of values to choose from. By entering more characters, the user can filter down the list to better matches.

This can be used to enter previous selected values, eg. for tags, to complete an address, eg. enter a city name and get the zip code, or maybe enter email addresses from an addressbook.

Current version: 1.0.2
Compressed filesize: 7596 bytes
License: MIT/GPL
Tested in: Firefox 2, IE 6 & 7, Opera 9, Safari 3

 

官方JS下载地址:http://bassistance.de/jquery-plugins/jquery-plugin-autocomplete/

[hadoop]Hadoop相关网络资源汇总

mikel阅读(1021)

(NOTE: 之前研究过的一些hadoop相关资料,在这里汇总起来,方便他人学习)
第一手资源
hadoop官方网站

最权威的官方资源之一

hadoop.cn(偶尔有一些有用信息)
手册

相关Blog
facebook工程师blog
hadoop0.19特性归纳
这个家伙很有意思,并且是研究hadoop的

http://www.blogjava.net/killme2008/archive/2008/06/05/206043.html


hadoop源码剖析不错的

http://caibinbupt.javaeye.com/blog/292073

也研究MapReduce的家伙



相关主题和文档



http://zkl-1987.javaeye.com/blog/365172

http://www.javaeye.com/topic/365172
hadoop namenode 高可用性(容灾)(Redundant Network Architecture, 相关软件有: Linux bonding, heartbeat
, DRBD Disk
)
http://www.hadoop.org.cn/document/Hadoop%20Namenode%20High%20Availability.pdf
图书

<<Pro hadoop>>
<<hadoop: the definitive guide>> (hadoop作者写的)
MISC

清华大学的分布式相关课程




[Flex]Flex与.NET互操作系列文章

mikel阅读(717)

    本系列文章主要介绍了关于Flex与.NET结合开发中的一些互操作性,包括网络通信、数据加载、数据传输、文件传输、以及应用于Flex与.NET协作开发的通信网关开源项目FluorineFx的相关知识点。

     开源项目FluorineFx就是专门针对.NET平台与Flex通信提供的AMF协议通信网关,我们可以通过FluorineFx很方便的完成与.NET的通信。 另外还可以轻松的实现及时文字沟通、视频语音通信等及时交互系统的开发。

     FluorineFx官方提供了安装包的下载和在线文档,可以帮助我们有效的利用FluorineFx来开发。 

     FluroineFx官方网站http://www.fluorinefx.com/    

     FluroineFx下载地址:http://www.fluorinefx.com/download.html

     FluroineFx在线文档:http://www.fluorinefx.com/docs/fluorine/index.html

     

     本系列文章的程序开发环境选择如下:

     .NET:Microsoft Visual Studio 2008 + .NET Framework 3.5

     Flex:Adobe Flex Builder CS3 + Flex SDK 3.2

     FluroineFx:FluorineFx v1.0.0.15 (点击可下载)

     文章目录如下:

     1、Flex与.NET互操作(一):基于Socket的网络连接

     2、Flex与.NET互操作(二):基于WebService的数据访问(上)

     3、Flex与.NET互操作(三):基于WebService的数据访问(下)

     4、Flex与.NET互操作(四):使用HttpService、URLReqeust和URLLoader加载/传输数据 

     5、Flex与.NET互操作(五):使用FileReference+HttpHandler实现文件上传/下载

     6、Flex与.NET互操作(六):Flex和.NET协同开发利器FluorineFx

     7、Flex与.NET互操作(七):了解FluorineFx的环境配置(远程对象、网关、通道、目的地)

     8、Flex与.NET互操作(八):使用FluorineFx网关实现远程访问

     9、Flex与.NET互操作(九):FluorineFx.NET的认证(Authentication )与授权(Authorization) 

   10、Flex与.NET互操作(十):FluorineFx.Net的及时通信应用(ApplicationAdapter)(一)  

   11、Flex与.NET互操作(十一):FluorineFx.Net的及时通信应用(Remote Procedure Call)(二)

   12、Flex与.NET互操作(十二):FluorineFx.Net的及时通信应用(Remote Shared Objects)(三)

   13、Flex与.NET互操作(十三):FluorineFx.Net实现视频录制与视频回放 (回复中有视频聊天的实现)

   14、Flex与.NET互操作(十四):FluorineFx的AMF(Action Message Format)协议通信

   15、Flex与.NET互操作(十五):使用FluorineFx中的字节数组(ByteArray)实现图片上传

 

      本系列文章暂时就写到这里,希望对学习基于.NET后台的Flex开发的朋友起到一定的帮助作用。另外在此谢谢长期以来支持我这一系列文章的朋友。

 

版权说明

  本文属原创文章,欢迎转载,其版权归作者和博客园共有。  

  作      者:Beniao

 文章出处:http://beniao.cnblogs.com/  或  http://www.cnblogs.com/

 

[Mobile]Windows Mobile开发资源文章列表

mikel阅读(641)

智能手机

手机词汇

研发手机基本流程

我理解的Windows moblie

J2ME,CompactFramework,c++,我该如何取舍

Windows Mobile Jump Start Guide

从0开始Windows Mobile 开发

3G 手机流媒体应用,看上去很美

基于rtsp的手机视频点播实现和研究

手机流媒体 
 

UI开发 

WINCE应用的UI实现方案 —— 上篇:几种UI实现方案比较

Windows Mobile 和 Wince 下的 WTL(Windows Template Library) 界面开发

Mobile个人开发(绘制背景图片)

怎样在Windows Mobile上设计一个美观的用户界面程序(Win32)

EVC中的图片背景透明处理

Windows Mobile载入位图的方法

[翻译]Windows Mobile应用程序设计指导-软键和菜单

创建Windows Mobile上兼容性好的UI 程序

windows mobile 5.0 下创建菜单

在Visual Studio 2005下创建WM for Smartphone/Standard 软键菜单的问题

AP的全屏与非全屏的切换

如何创建在 PocketPC 全屏幕应用程序(转)

关于wince中的全屏显示

用本地代码实现屏幕方向自适应的Windows Mobile程序

mobile手机上窗体最小化后置icon在消息栏的处理.

 

GPRS开发系列 

GPRS入门知识

GPRS开发系列文章之入门篇(转)

GPRS开发系列文章之进阶篇

GPRS开发系列文章之实战篇(转)

GPRS技术在配电监控系统中的应用[转载]

WM5.0下连接移动GPRS

Windows Mobile中如何建立GPRS连接以便Socket能正常通信

PDA/PPC下如何获取GPRS的网络流量(ZT)

windows ce gprs 拨号程序(转)

C# wm6通过udp协议和pc通讯

 

.NET Compact Framework

.NET Compact Framework 多线程下的等待事件

.NET Compact Framework 多线程环境下的UI异步刷新

定时关闭窗口 For Windows Mobile SP/PPC

Microsoft .NET CF 与非托管代码交互注意事项

.NET Compact Framework 下的3G应用

在.NET Compact Framework调用PPC设备的震动功能

.Net Compact Framework 基础篇(1)

.Net Compact Framework 基础篇(4)

.Net Compact Framework 高级篇(1)

列车时刻表 开发回顾 (一):后台线程更新前端界面

 

开发环境 + 模拟器使用 + 疑难杂症 

VS无法调试智能设备程序的解决方案

在Windows Mobile Emulator建立网络连接

配置PPC模拟器网络环境,调试TCP/UDP套接字程序

Windows Mobile 2003 SE 模拟器上网设置

Ring Tone Manager on Windows Mobile

Windows Mobile Device Emulator In-Depth–(1)

Windows Mobile Device Emulator In-Depth–(2)

在Visual Studio 2005里,用ActiveSync来同步模拟器(Windows Mobile 5.0 For Smartphone)

也谈EVC工程移植

手机音频流媒体应用与优化指南

ANSI码和UNICODE码转化

WCHAT、TCHAT、CString和char*的转换(WM5.0)

WinCe和Windows Mobile下的字符串转换

【转】使用 AYGShell 实现 Windows CE .NET 和 Pocket PC 2002 外壳兼容性

[转]从AP中获取电池和电源信息变更通知的方法

中文问题-Mobile-UrlEncode

如何判断当前WM系统是否是Smartphone?

利用tmail.exe 命令参数来发送邮件

 

其它资源 

Wince 

Windows Mobile

Windows Mobile 开发工具和资源

移动开发索引贴  

平时收获,供需及取(PPC)

Mobile开发之路_之小总结

WINCE 开发资料汇集

iPhone开发知识介绍

symbian中的新手问题整理(均有解答)

Mobile.ConnectionMonitor

Windows Mobile-Bookmarks

Windows Mobile 系列文章索引—不断整理中(2009-04-04)

H.264系列视频编解码器代码下载(Windows和Windows CE/Windows Mobile版本)

手机音视频流媒体开发一些有用资料

水煮TCPMP

WinCE开发流媒体播放器--MPEG4

Windows Mobile 开发资源

Windows Mobile 常用键值(VK)对应表及系统文件夹简单介绍

 

 

具体应用开发文章 

WM性能优化的一些经验

Windows Mobile SP/PPC 中 Menu Bar 使用完美方案

Windows Mobile平台上重写Back健的行为

也谈Windows Mobile中打开/关闭WIFI

VC通用控件自适应屏幕类

在非纯色背景上,叠加背景透明的BUTTON和STATIC_TEXT控件

在Windows mobile 5.0下操作INI文件

WinMoblie 利用EVC读写INI,XML配置文件

windows mobile 5.0 下创建菜单

Windows Mobile 发送短信的问题

3G应用—windows mobile和symbian平台下rtsp流媒体播放器

[流媒体]实例解析MMS流媒体协议,下载LiveMediaVideo[1][修正版,增加了带宽测试包]

[J2ME]手机看交通监视器实时录像 实现说明

[J2ME]手机流媒体之实作[附源码][与RTSP/MMS协议无关]

【蛙蛙推荐】手机通讯录实现

[Flex]Flex与.NET互操作(十五):使用FluorineFx中的字节数组(ByteArra

mikel阅读(873)

     前几天一位朋友问我一个问题,他说:“我用HTTP接口或是WebService接口可以实现图片上传功能,那么用FluorineFx 如何实现图片上传功能呢?”,其实仔细看官方文档和示例程序的自己都可以找到答案,实现上传可以有很多种实现,这里我以官方所提供是示例为基础稍加改动, 通过ByteArray类实现图片上传。

      首先建立FluorineFx库和网站,在远程服务器类里添加一个处理文件上传的方法,详细代码如下:

namespace ByteStream.Services
{
    [RemotingService]
    
public class ByteStreamService
    {
        
public ByteArray UploadImage(ByteArray ba)
        {
            MemoryStream ms 
= new MemoryStream(ba.GetBuffer());
            Image img 
= Bitmap.FromStream(ms);

            Bitmap newImage 
= new Bitmap(img);
            MemoryStream tempStream 
= new MemoryStream();
            newImage.Save(tempStream, System.Drawing.Imaging.ImageFormat.Png);
            
string path = HttpContext.Current.Server.MapPath("UpLoad/ByteArray.png");
            FileStream fs 
= new FileStream(path, FileMode.Create);
            tempStream.WriteTo(fs);
            fs.Close();
            ByteArray result 
= new ByteArray(tempStream);
            
return result;
        }
    }
}

 

      处理图片上传的方法通过把flex客户端传递来的字节数组包装为内存流,然后通过写文件的形式将图片保存到指定的目录下。示例中提供了 一个画图板,用户可以通过选择颜色自画不同的图象,然后保存到服务器上指定的目录。画图板的实现是根据鼠标按下的移动路线做的,代码如下:

private function doMouseDown():void
{
    x1 
= myCanvas.mouseX;
    y1 
= myCanvas.mouseY;
    isDrawing 
= true;
}
private function doMouseMove():void
{
    x2 
= myCanvas.mouseX;
    y2 
= myCanvas.mouseY;
    
if (isDrawing)
    {
        myCanvas.graphics.lineStyle(
2, drawColor);
        myCanvas.graphics.moveTo(x1, y1);
        myCanvas.graphics.lineTo(x2, y2);
        x1 
= x2;
        y1 
= y2;
    }
}
private function doMouseUp():void
{
    isDrawing 
= false;
}
//清空画图板
private function onErase(event:MouseEvent):void
{
    myCanvas.graphics.clear();
}

      

      在官方实例中是使用的RemoteObject实现的,这里我将其修改为通过编程实现AMF通信实现当程序初始化的时候就建立与FluorineFx网关的AMF通信连接:

private var nc:NetConnection;
private var rs:Responder;
private function init():void
{
    rs 
= new Responder(onResult,onFault);
    nc 
= new NetConnection();
    nc.connect(
"http://localhost:2453/FluorineFxWeb/Gateway.aspx")
    nc.client 
= this;
}

 

      在Flex客户端通过当前网络连接的call()方法实现远程方法调用,并指定通过Responder来处理服务器端方法的返回结果。

private function onSaveImage(event:MouseEvent):void
{
    var bd:BitmapData 
= new BitmapData(myCanvas.width,myCanvas.height);
    bd.draw(myCanvas);
    var ba:ByteArray 
= new PNGEncoder().encode(bd);
    nc.call(
"ByteStream.Services.ByteStreamService.UploadImage",rs,ba);
}

 

小提示

      在进行Flex开发中,能够通过编程实现的最好通过编程实现,尽量少的去使用Flex组件,这样可以有效的给Flex程序瘦身。

 

      服务器端将传递过去的ByteArray数据返回到了客户端,客户端接收到这些数据通过处理将字节数组转化为显示对象后显示到界面上。

private function onResult(result:ByteArray):void
{
    var loader:Loader 
= new Loader();
    loader.contentLoaderInfo.addEventListener(Event.COMPLETE,loaderCompleteHandler);
    loader.loadBytes(result);
}
private function loaderCompleteHandler(event:Event):void
{
    var loader:Loader 
= (event.target as LoaderInfo).loader;
    loader.contentLoaderInfo.removeEventListener(Event.COMPLETE,loaderCompleteHandler);
    var pictureHolder:UIComponent 
= new UIComponent();
    pictureHolder.addChild(loader);
    
this.resultImage.width = myCanvas.width;
    
this.resultImage.height = myCanvas.height;
    
this.resultImage.addChild(pictureHolder);
}
private function onFault(event:Object):void
{}

 

      到此就完成了图片上传功能,下面是完整的Flex客户端代码:


<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" fontSize="12" creationComplete="init()">
    
<mx:Script>
        
<![CDATA[
            import mx.core.UIComponent;
            import mx.controls.Alert;
            import mx.events.ResizeEvent;
            import mx.graphics.codec.PNGEncoder;
            import mx.rpc.events.FaultEvent;
            import mx.rpc.events.ResultEvent;
            
            
private var isDrawing:Boolean=false;
            
private var x1:int;
            
private var y1:int;
            
private var x2:int;
            
private var y2:int;
            
private var drawColor:uint;
            
            
private var nc:NetConnection;
            
private var rs:Responder;
            
private function init():void
            
{
                rs 
= new Responder(onResult,onFault);
                nc 
= new NetConnection();
                nc.connect(
"http://localhost:2453/FluorineFxWeb/Gateway.aspx")
                nc.client 
= this;
            }

            
            
private function onSaveImage(event:MouseEvent):void
            
{
                var bd:BitmapData 
= new BitmapData(myCanvas.width,myCanvas.height);
                bd.draw(myCanvas);
                var ba:ByteArray 
= new PNGEncoder().encode(bd);
                nc.call(
"ByteStream.Services.ByteStreamService.UploadImage",rs,ba);
            }

            
            
private function onResult(result:ByteArray):void
            
{
                var loader:Loader 
= new Loader();
                loader.contentLoaderInfo.addEventListener(Event.COMPLETE,loaderCompleteHandler);
                loader.loadBytes(result);
            }

            
private function loaderCompleteHandler(event:Event):void
            
{
                var loader:Loader 
= (event.target as LoaderInfo).loader;
                loader.contentLoaderInfo.removeEventListener(Event.COMPLETE,loaderCompleteHandler);
                var pictureHolder:UIComponent 
= new UIComponent();
                pictureHolder.addChild(loader);
                
this.resultImage.width = myCanvas.width;
                
this.resultImage.height = myCanvas.height;
                
this.resultImage.addChild(pictureHolder);
            }

            
            
private function onFault(event:Object):void
            
{}
            
            
private function doMouseDown():void
            
{
                x1 
= myCanvas.mouseX;
                y1 
= myCanvas.mouseY;
                isDrawing 
= true;
            }

            
private function doMouseMove():void
            
{
                x2 
= myCanvas.mouseX;
                y2 
= myCanvas.mouseY;
                
if (isDrawing)
                
{
                    myCanvas.graphics.lineStyle(
2, drawColor);
                    myCanvas.graphics.moveTo(x1, y1);
                    myCanvas.graphics.lineTo(x2, y2);
                    x1 
= x2;
                    y1 
= y2;
                }

            }

            
private function doMouseUp():void
            
{
                isDrawing 
= false;
            }

            
//清空画图板
            private function onErase(event:MouseEvent):void
            
{
                myCanvas.graphics.clear();
            }

        ]]
>
    
</mx:Script>
    
    
<mx:Panel x="10" y="10" width="348" height="306" layout="absolute">
        
<mx:Canvas x="10" y="10" width="315" height="210" id="myCanvas"
            mouseDown
="doMouseDown()"
            mouseMove
="doMouseMove()"
            mouseUp
="doMouseUp()">
        
</mx:Canvas>
        
<mx:ControlBar>
            
<mx:ColorPicker change="drawColor = event.target.selectedColor"/>
            
<mx:Button label="清除" click="onErase(event)"/>
            
<mx:Button label="保 存" click="onSaveImage(event)"/>
        
</mx:ControlBar>
    
</mx:Panel>
    
<mx:Image x="382" y="10" id="resultImage"/>
</mx:Application>

 

      本文示例程序下载:ByteStreamDemo.rar

版权说明

  本文属原创文章,欢迎转载,其版权归作者和博客园共有。  

  作      者:Beniao

 文章出处:http://beniao.cnblogs.com/  或  http://www.cnblogs.com/

 

[MVC]Asp.net MVC FluentHTML and Fluent Interface

mikel阅读(716)

      赏花归去马如飞, 去马如飞酒力微.
        酒力微醒时已暮
, 醒时已暮赏花归. —苏轼

        

  我们力求页面层代码简洁并具有较好的可读性,ASP.NET MVC的平台上,我们以新的起点来实现这一目标.MvcContrib.FluentHtmlSpark ViewEngine给我们做出了榜样.本文将以MvcContrib.FluentHtml为例探究它的实现机制:Fluent Interface.

 

       读过开篇的诗句,不知是否感受到文字之美.不仅仅是在文学作品中,在代码中,这种美一样存在.

 MvcContrib.FluentHtml的应用中,我们随处可以见到下面的代码:

 

    <%= this.TextBox(x => x.Person.Name).Title("Enter the person's name").Label("Name:"%><br />
        
        …  …        
        
<%= this.Select(x => x.Person.Gender).Options(Model.Genders).Size(5).Label("Gender:")
                .Title(
"Select the person's gender"%><br /> 
 浏览器中生成的代码为:
<label id="Person_Name_Label" for="Person_Name">Name:</label>
<input id="Person_Name" type="text" value="Jeremy" title="Enter the person's name" name="Person.Name" maxlength="50"/>
 .
<select id="Person_Gender" title="Select the person's gender" size="5" name="Person.Gender">
<option value="M" selected="selected">Male</option>
<option value="F">Female</option>
</select>

 

上面对动态生成TextBoxSelect的代码很有意思,我们使用普通的方式在页面上生成同样的客户端代码,CS代码大致是这样的:

                 Label label = new Label();

        label.Text = "Name";

        TextBox textbox= new TextBox();

        textbox.ToolTip ="Enter the person's name";

        textbox.ID = "No.10001";

        textbox.ID = "Person.Name";

 

FluentHtml创建页面元素的方式让我们很容易联想到StringBuilder的使用:

   StringBuilder stringbuilder = new StringBuilder();

   stringbuilder.Append("Hello").Append(" ").Append("World!");

 

Fulent Interface

     这种实现编程方式就是"Fluent Interface",这并不是什么新概念,2005Eric Evans Martin Fowler就为这种实现方式命名.源文档 <http://www.martinfowler.com/bliki/FluentInterface.html> 可以通过维基百科中对Fluent Interface的描述获得一个基本的了解:In software engineering, a fluent interface (as first coined by Eric Evans and Martin Fowler) is a way of implementing an object oriented API in a way that aims to provide for more readable code.

我们分解上面的话:

  • 它是面向对象API的一种实现方式
  • 目的是增加代码的可读性

既然我们最熟悉的是StringBuilder,我们就从这个线索追下去:打开Re

flector,很容易找到StringBuilderAppend方法:

public StringBuilder Append(string value)
{
    
if (value != null)
    
{
        
string stringValue = this.m_StringValue;
        IntPtr currentThread 
= Thread.InternalGetCurrentThread();
        
if (this.m_currentThread != currentThread)
        
{
            stringValue 
= string.GetStringForStringBuilder(stringValue, stringValue.Capacity);
        }

        
int length = stringValue.Length;
        
int requiredLength = length + value.Length;
        
if (this.NeedsAllocation(stringValue, requiredLength))
        
{
            
string newString = this.GetNewString(stringValue, requiredLength);
            newString.AppendInPlace(value, length);
            
this.ReplaceString(currentThread, newString);
        }

        
else
        
{
            stringValue.AppendInPlace(value, length);
            
this.ReplaceString(currentThread, stringValue);
        }

    }

    
return this;
}

 

阅读这段有两个特别要注意的点:1.方法的返回值是StringBuilder类型 2.最后一句:return this;为了深刻理解,我们写一个简单的StringBuilder:

 

public interface IContentBuilder
    {
        
void WriteContent();
        IContentBuilder Append(
string partialContent);
    }
    
public class TestContentBuilder : IContentBuilder
    {
        
string temp;
        
#region IContentBuilder Members
        
void IContentBuilder.WriteContent()
        {
            Console.Write(temp);
        }
        IContentBuilder IContentBuilder.Append(
string partialContent)
        {
            temp 
+= partialContent;
            
return this;
        }
        
#endregion
    }
… …
//调用代码
IContentBuilder t = new TestContentBuilder();
 t.Append(
"test").Append("Hello").WriteContent();

 

跑一下代码,StringBuilder效果是一样的.从上面的应用也可以看出:Fluent Interface经常用来完成对象的构造和属性赋值.

 

言归正传:FluentHTML

      了解了Fluent Interface,我们来看一下MVCContrib.FluentHTML的实现,这里以TextBox为例进行考察,首先看一下它的继承关系:

public class TextBox : TextInput<TextBox>

public abstract class TextInput<T> : Input<T>, ISupportsMaxLength where T : TextInput<T>

public abstract class Input<T> : FormElement<T> where T : Input<T>, Ielement

泛型是一种高层次的算法抽象,我们就通过Input<T>一窥端倪:

 

public abstract class Input<T> : FormElement<T> where T : Input<T>, IElement
{
    
protected object elementValue;
    
protected Input(string type, string name) : base(HtmlTag.Input, name)
    {
        builder.MergeAttribute(HtmlAttribute.Type, type, 
true);
    }
    
protected Input(string type, string name, MemberExpression forMember, IEnumerable<IBehaviorMarker> behaviors)
        : 
base(HtmlTag.Input, name, forMember, behaviors)
    {
        builder.MergeAttribute(HtmlAttribute.Type, type, 
true);
    }
    
/// <summary>
    
/// Set the 'value' attribute.
    
/// </summary>
    
/// <param name="value">The value for the attribute.</param>
    public virtual T Value(object value)
    {
        elementValue 
= value;
        
return (T)this;
    }
    
/// <summary>
    
/// Set the 'size' attribute.
    
/// </summary>
    
/// <param name="value">The value for the attribute.</param>
    public virtual T Size(int value)
    {
        Attr(HtmlAttribute.Size, value);
        
return (T)this;
    }
    
protected override void PreRender()
    {
        Attr(HtmlAttribute.Value, elementValue);
        
base.PreRender();
    }
}

 

Size方法为例,可以看出这是一种典型的Fluent Interface实现:

public virtual T Size(int value)

{

Attr(HtmlAttribute.Size, value);

return (T)this;

}

分析到这里,上面的语句中还有一点比较奇怪,就是Lambda表达式的部分:

this.TextBox(x => x.Person.Name).Title("Enter the person's name").Label("Name:")

TextBox的实现代码里面我们没有看到对Lambda表达式的支持.那是在什么地方完成的呢?通过跟进,我们来到了ViewDataContainerExtensions,它是IViewDataContainer Extension Method:

 

namespace MvcContrib.FluentHtml
{
    
/// <summary>
    
/// Extensions to IViewDataContainer
    
/// </summary>
    public static class ViewDataContainerExtensions
    {
        
/// <summary>
        
/// Generate an HTML input element of type 'text' and set its value from ViewData based on the name provided.
        
/// </summary>
        
/// <param name="view">The view.</param>
        
/// <param name="name">Value of the 'name' attribute of the element.  Also used to derive the 'id' attribute.</param>
        public static TextBox TextBox(this IViewDataContainer view, string name)
        {
            
return new TextBox(name).Value(view.ViewData.Eval(name));
        }
… … 

  看一下return new TextBox(name).Value(view.ViewData.Eval(name));所以这里就成了TextBox定义方法链的第一步.

 

总结

       为了能够在View中能够简洁清晰的构造HTML元素,ASP.NET MVC中通过htmlHelper.InputHelper来实现页面元素的构造. 页面层所使用的<%= Html.TextBox("username") %>,HTML也是htmlHelperExtension Method.相比较起来,htmlHelper提供了基础的页面控件定义和构造,FluentHTML表现的更为灵活.除了FluentHTML,著名的Spark View Engine也有类似的实现,大家可以关注一下.

[优化]自己动手写个ORM实现(4) 关于反射DataRow数据记录到实体性能的优化

mikel阅读(682)

总所周知,反射对于运行时确定对象类型十分方便,但是它最大的不足就是效率低下,比直接调用的效率慢了一百倍有余。

在3.5以前有codeDom或借助Emit直接编写IL来优化其效率,但是使用不便,借助3.5新增的Expression,让我们有了一种既简洁,在速度上又较反射有很大的提高。 示例如下


 1 public static T GetEntityByDataRowSlow<T>(this DataRow data) where T : new()
 2         {
 3             T t = new T();
 4             PropertyInfo[] properties = typeof(T).GetProperties();
 5 
 6             foreach (PropertyInfo p in properties)
 7             {
 8                 object value = data[p.Name] == DBNull.Value ? null : data[p.Name];
 9                 p.SetValue(t, value, null); 
10             }
11             return t;
12         }

 

如上,整段代码慢就慢在p.SetValue(t,value,null)这段上。 也有可能有人会说 typeof(T).GetProperties()获取所有属性应该缓存,但实际测试结果看下来影响并不大,效率相差无几。

接下来,主角登场了

 

 1 static Func<T, objectobject> GetSetDelegate<T>(MethodInfo m,Type type)
 2         {
 3            
 4             var param_obj = Expression.Parameter(typeof(T), "obj");
 5             var param_val = Expression.Parameter(typeof(object), "val");
 7             var body_val = Expression.Convert(param_val, type);
 8             var body = Expression.Call(param_obj, m, body_val);
 9             Action<T, object> set = Expression.Lambda<Action<T, object>>(body, param_obj,  param_val).Compile();
10             return (instance, v) =>
11             {
12                 set(instance, v);
13                 return null;
14             };
15         }

 

1 static void FastSetValue<T>(this PropertyInfo property,T t, object value)
2         {
3             MethodInfo m = property.GetSetMethod();
4             GetSetDelegate<T>(m,property.PropertyType)(t, value);
5         }

 

关于Expression和lambda的介绍可参看园里大牛赵哥的文章  方法的直接调用,反射调用与……Lambda表达式调用

经过改良的调用方法

 

 

public static T FastGetEntityByDataRow<T>(this DataRow data) where T : new()
        {
            T t 
= new T();
            PropertyInfo[] properties 
= GetProperties(typeof(T));
            
            
foreach (PropertyInfo p in properties)
            {                    
                
object value = data[p.Name] == DBNull.Value ? null : data[p.Name];
                p.FastSetValue
<T>(t, value);
            }
            
return t; 
        }

 

经过测试下来  如果直接是Entity.Property = "somevalue"设置属性的速度比值是1的话,反射的速度比值是100多,而经过改良的上述方法比值在2-3之间。

尽管这样,常见Web应用的主要瓶颈还是在结构的设计,数据库的读取,上面的方法对于整个程序框架的影响也只是积跬步,单用这个地方用了也几乎白用,不用白不用。谨记录一下。

 

[AsWing]AsWing中文教程下载

mikel阅读(853)

After half year part-time writting, the book is finished, as original plan, it will be published as a papery book in chinese, but for some reason, now it can’t. So i released it as a e-book for free, and accept donation.

aswing book

aswing book

You can download it here : http://code.google.com/p/aswing/downloads/list

I plan to hire some one to translate it into english, so the most donation money will be used for the translation, if some one can help the translation, that will be cool, contact me!

[优化]利用Emit减少反射的性能损失

mikel阅读(1020)

我很喜欢在程序里使用反射,让事 情变得更简单、灵活。但是在获得便利的同时带来的是性能上的损失。粗略的测试一下,通过反射根据成员名字去访问成员比直接访问慢250倍左右。听起来挺吓 人,但是以时间来算,用我的p4 2.66G的机用反射访问成员一次耗时仅3微秒,对与整个程序的运行周期看来,这占的时间微不足道。
不过我用反射的程度确实过分了点。我很久以前就做过这么一样东西,利用反射实现asp.net控件和数据之间的双向绑定。意料之中的是,有人对我仅为了赋值,取值就使用反射提出质疑。.net阵营不像java那样财大气粗,很多人对性能还是很看重的,風語·深蓝甚至还被上司禁止使用工厂模式,说Activator.CreateInstance会影响性能…
于 是,我开始在思考如何减少反射带来的性能损失。首先元数据可以缓存起来,这样就不必重复执行GetTypes(), GetMembers()等方法了,不过这些操作耗时很少,在程序中用到的地方也少,最重要还是要解决如何能快速的通过传入一个对象和对象的属性名去访问 属性。要大幅提高性能,唯一办法就是不要用反射。。。
还能怎样呢?我想到了一个有这样结构的类:
这个类有GetValue和SetValue方法,通过一堆case去根据参数去读或写相应的属性,用这种方法就能达到我想要的效果,而又不需要反射了。
但是这样针对每一个类,就要有另一个对应的类去处理这样的事情,所以这些负责Get/Set的类应该在运行时动态生成,这就得靠反射最高级的特性-Emit了。
利用System.Reflection.Emit中的类,可以运行时构造类型,并且通过IL去构造成员。当然,生成C#代码用CodeDom编译也可以,但是速度肯定大打折扣了。
跟着我开始动手,先定义IValueHandler接口:

using System;
namespace NoReflection
{
    
internal interface IValueHandler {
        
object GetValue(object o, string expression);
        
void SetValue(object o,string expression, object value);
        
object CreateInstance();
    }
}

然后定义一个叫ObjectUtil类,会用动态构造出用来处理特定类型的IValueHandler的实现类,然后把它放到缓存里。通过几个方法的包装,根据需要调用ValueHandler的GetValue/SetValue。
不 要把构造IL想的太恐怖,其实只要对CLI和MSIL有一定的了解,并且能看懂就行了,因为我可以先用熟悉的C#写好代码,编译后再反汇编去看,大部分可 以抄。当然这个过程还是花了我很多时间,因为IL里头装箱/拆箱得自己管,不同类型的数据转换的代码又各不相同,然后还发现用short form指令的话如果目标地址的偏移量超过了8位/*双鱼座纠正说是7位…*/就会出错,所以xx.s的指令就不能照抄,统统用xx代替。。。
SQLConnection的处理来举例,动态生成的类是这个样子的:

public class ValueHandler : IValueHandler
{
    
// Methods
    public ValueHandler()
    {
    }
    
public override object CreateInstance()
    {
        
return new SQLConnection();
    }
    
public override object GetValue(object obj, string property)
    {
        
switch (property)
        {
            
case "ConnectionString":
                {
                    
return ((SQLConnection) obj).ConnectionString;
                }
            
case "ConnectionTimeout":
                {
                    
return ((SqlConnection) obj).ConnectionTimeout;
                }
            
case "Database":
                {
                    
return ((SqlConnection) obj).Database;
                }
            
case "DataSource":
                {
                    
return ((SqlConnection) obj).DataSource;
                }
            
case "PacketSize":
                {
                    
return ((SqlConnection) obj).PacketSize;
                }
            
case "WorkstationId":
                {
                    
return ((SqlConnection) obj).WorkstationId;
                }
            
case "ServerVersion":
                {
                    
return ((SqlConnection) obj).ServerVersion;
                }
            
case "State":
                {
                    
return ((SqlConnection) obj).State;
                }
            
case "Site":
                {
                    
return ((SqlConnection) obj).Site;
                }
            
case "Container":
                {
                    
return ((SqlConnection) obj).Container;
                }
        }
        
throw new Exception("The property named " + property + " does not exists");
    }
    
public override void SetValue(object obj, string property, object value)
    {
        
switch (property)
        {
            
case "ConnectionString":
                {
                    ((SqlConnection) obj).ConnectionString 
= (string) value;
                    
return;
                }
            
case "Site":
                {
                    ((SqlConnection) obj).Site 
= (ISite) value;
                    
return;
                }
        }
        
throw new Exception("The property named " + property + " does not exists");
    }
}

 ObjectUtil与ASP.NET里的DataBinder用法十分相似,不过DataBinder只能Get,ObjectUtil可以 Get/Set。为了最大的提高性能,我把简单的属性表达式和跨对象的复杂表达式区分对待,例如SqlCommand的CommandText应该使用 ObjectUtil.GetValue(cmd, "CommandText"); 而要得到他的Connection的ConnectionString,则要调用ObjectUtil.GetComplexValue(cmd, "Connection.ConnectionString")。因为GetComplexValue方法多了个对参数Split('.')的操作,如果 是跨对象表达式的则要从左到右一步步获得对象引用,再Get/Set最终对象属性的值。不要小看一次Split(),它已经会使整个过程多花近50%的时 间了。另外也支持对索引器的访问,这里我把表达式规则小改了一下,DataBinder使用和开发语言语法一致的表达式,并且同时兼容VB.NET和C# 语法,例如可以使用DataBinder.Eval(myList, "[0]")或DataBinder.Eval(myList, "(0)")访问索引为0的元素,而ObjectUtil规定了整型的索引直接使用数字,例如OjbectUtil.GetValue(myList, "0"),字符型的索引直接传入字符,如OjbectUtil.GetValue(myList, "someKey")。这样做的原因,一是节省了分析方括号的时间,二是我也省了不少事 🙂
这是生成的处理NameValueCollection的类,比较有代表性,索引器可以是int或string:

public override object GetValue(object obj3, string text1)
{
      
switch (text1)
      {
            
case "AllKeys":
            {
                  
return ((NameValueCollection) obj3).AllKeys;
            }
            
case "Count":
            {
                  
return ((NameValueCollection) obj3).Count;
            }
            
case "Keys":
            {
                  
return ((NameValueCollection) obj3).Keys;
            }
      }
      
if (char.IsDigit(text1[0]))
      {
            
return ((NameValueCollection) obj3)[Convert.ToInt32(text1)];
      }
      
return ((NameValueCollection) obj3)[text1];
}
 

跟着就是测试性能了。我拿ObjectUtil和反射、DataBinder、Spring.Net的ObjectNavigator来做对比。对比结果是:
如果是简单表达式,速度是反射的3.5倍,DataBinder的7倍,ObjectNavigator的15倍。。。这东西真是有java特色啊
复杂表达式,是反射的1.5倍,DataBinder的3.5倍,ObjectNavigator的6.5倍。
由于ObjectUtil用法和DataBinder和ObjectNavigator类似,比直接反射简单的多,以他们为参照比较合适。成绩算不错了 🙂
CreateInstance是后来顺便加上的,用默认的构造函数去创建对象。看来还很有必要,有些类型的对象用反射创建耗时极长,我也不知原因,就拿SqlCommand来说,用ObjectUtil创建比用反射快超过40倍
当然,在实际应用中,它带来的效果通常不太明显,原因就是我前面所说的,在整个程序执行期间,反射耗时仅占极少一部分。例如我曾经用NHibernate 0.8做测试,性能仅提高了3%左右,因为大部分时间花在了分析HQL和数据库读取上。但是用在大部分时间在反射的ObjectComparer上,效果不错,用ObjectUtil替换后速度是原来3倍
源码 /Files/Yok/NoReflection.rar
生成的类 /Files/Yok/EmittedDlls.rar

[测试]自动测试框架Tellurium快速上手指南.

mikel阅读(909)

TelluriumQuickStart  

Tellurium快速上手指南.

简介

Tellurium 是一个开源的网页测试框架,现阶段还是建立在Selenium之上。 但有很多独特的测试理念。 比之Selenium, 维护性,鲁棒性, 和可复用性都要好。 它支持JUnit和TestNG。Tellurium的测试代码可以用Java, Groovy和纯DSL脚本来写.

Tellurium子项目

Tellurium由以下子项目构成:

一点Tellurium概念

虽然Tellurium脱胎于Selenium,但两者在概念上有很大的不同。Selenium主要是用记录和重播(Record and Replay)模式,而Tellurium要求你首先定义待测的UI模块。下面列出Tellurium的一些主要概念:

Tellurium物件

Tellurium定义了一些常用的物件,如Button, Table, Form等。

Tellurium物件 缺省属性
Button tag: "input"
Container
CheckBox tag: "input", type: "checkbox"
Div tag: "div"
Form tag: "form"
Image tag: "img"
InputBox tag: "input"
RadioButton tag: "input", type: "radio"
Selector tag: "select"
Span tag: "span"
SubmitButton tag: "input", type: "submit"
Table tag: "table"
UrlLink tag: "a"
StandardTable tag: "table"

值得注意的是Tellurium物件大多为抽象物件,比如Container就可以实用于不同的HTML标签。每个Tellurium物件都有一个uid,即它的别名。

Locator

Locator是用来定位一个元素在网页DOM中的位置,Tellurium支持两种Locator, 一种叫Base Locator, 用“locator”标识,它是一个相对的XPath. 如:

InputBox(uid: "SearchBox", locator: "//input[@title='Google Search']")

另一个是Composite Locator, 用“clocator”来标识,它是由一组属性构成,如

InputBox(uid: "SearchBox", clocator: [title: "Google Search"])

Composite Locator_是Tellurium的缺省Locator, 它容易写,表叙性好,方便动态生成Runtime Locator.

UI模块

UI模块是一个复合的Tellurium物件,它是由一些单个Tellurium物件嵌套构成。一个UI模块往往代表DOM的一个子树。比如Google首页搜索模块就可以表叙为

ui.Container(uid: "GoogleSearchModule", clocator: [tag: "td"], group: "true"){
   InputBox(uid: "Input", clocator: [title: "Google Search"],respond: ["focus", "mouseOver"])
   SubmitButton(uid: "Search", clocator: [name: "btnG", value: "Google Search"])
   SubmitButton(uid: "ImFeelingLucky", clocator: [value: "I'm Feeling Lucky"])
}

UI 模块的最外层元素以定要以"ui."开始。这里group为“true”表示Tellurium用利用UI元素之间的关系来协助它们在网页DOM中的定 位。respond属性定义了InputBox需要触发“focus”和“mouseOver”事件,Tellurium会自动触发这些事件的。

Tellurium测试案例

Tellurium 测试代码可以用Java, Groovy, 或纯DSL脚本来写。无论哪种方法,Tellurium要求你定义独立的UI模块,使之和测试代码分离,以便于维护。UI模块必须继承Tellurium 的DslContext class, 一般你还需定义对UI模块的操作方法。例如:

class GoogleSearchModule extends DslContext{
   public void defineUi() {
         ui.Container(uid: "google_start_page", clocator: [tag: "td"], group: "true"){
            InputBox(uid: "searchbox", clocator: [title: "Google Search"])
            SubmitButton(uid: "googlesearch", clocator: [name: "btnG", value: "Google Search"])
            SubmitButton(uid: "Imfeelinglucky", clocator: [value: "I'm Feeling Lucky"])
        }
   }
   def doGoogleSearch(String input){
        keyType "searchbox", input
        pause 500
        click "googlesearch"
        waitForPageToLoad 30000
    }
    def doImFeelingLucky(String input){
        type "searchbox", input
        pause 500
        click "Imfeelinglucky"
        waitForPageToLoad 30000
    }
}

如果你的测试案例用JUnit来写,你需要继承TelluriumJavaTestCase.

public class GoogleSearchTestCase extends TelluriumJavaTestCase {
    private static GoogleSearchModule gsm;
   
    @BeforeClass
    public static void initUi() {
        gsm = new GoogleSearchModule();
        gsm.defineUi();
    }
    @Before
    public void connectToGoogle() {
        connectUrl("http://www.google.com");
    }
    @Test
    public void testGoogleSearch() {
        gsm.doGoogleSearch("tellurium . ( Groovy ) Test");
    }
    @Test
    public void testGoogleSearchFeelingLucky() {
        gsm.doImFeelingLucky("tellurium automated Testing");
    }
}

TestNG的案例类似,除了你要继承TelluriumTestNGTestCase。如果用Groovy, 你需要继承TelluriumGroovyTestCase.

Tellurium配置

Tellurium用一个配置文件TelluriumConfig.groovy来配置系统。它包括对Selenium服务器和Tellurium框架本身的配置,如:

tellurium{
    //embedded selenium server configuration
    embeddedserver {
        //port number
        port = "4445"
        //whether to use multiple windows
        useMultiWindows = false
        runInternally = true
        profile = ""
    }
    //event handler
    eventhandler{
        //whether we should check if the UI element is presented
        checkElement = true
        //wether we add additional events like "mouse over"
        extraEvent = true
    }
    //data accessor
    accessor{
        //whether we should check if the UI element is presented
        checkElement = false
    }
    connector{
        //selenium server host
        //please change the host if you run the Selenium server remotely
        serverHost = "localhost"
        //server port number the client needs to connect
        port = "4445"
        //base URL
        baseUrl = "http://localhost:8080"
        //Browser setting, valid options are
        //  *firefox [absolute path]
        //  *iexplore [absolute path]
        //  *chrome
        //   *iehta
        browser = "*chrome"
    }
    datadriven{
        dataprovider{
            reader = "PipeFileReader"
        }
    }
    test{
        result{
            reporter = "XMLResultReporter"
            output = "Console"
            filename = "TestResult.output"
        }
        exception{
            captureScreenshot = true
            filenamePattern = "Screenshot?.png"
        }
    }
    uiobject{
        builder{
            //example:
           SelectMenu="org.tellurium.builder.SelectMenuBuilder"
        }
    }
    widget{
        module{
            //define your widget modules here, for example Dojo or ExtJs
            included=""
        }
    }
}

此外,Tellurium还提供了方法让用户来覆盖Tellurium中的配置,

public class GoogleSearchModuleTestCase extends TelluriumJavaTestCase
{
   static{
       setCustomConfig(true, 5555, "*chrome", true, null);
   }
...
}

运行Tellurium的条件

由于Tellurium的UI模块必须是一个Groovy class, 你需要Groovy才能运行Tellurium. 请从Groovy官方网页下载Groovy,当然,你也可以用Maven下载。

在IDE中运行Tellurium, 你需要安装Groovy插件。Eclipse的Groovy插件在: http://dist.codehaus.org/groovy/distributions/update/. 新版的Netbeans和IntelliJ本身就带有Groovy插件。

创建自己的Tellurium测试项目

有三种方法创建自己的Tellurium测试项目。一是从Tellurium下载网页下载文件手工创建,这样比较费事。或者下载Tellurium的参考项目,用它作为你的模板项目。更方便的方法是用Tellurium的Maven archetype来创建,非常简单,一个Maven命令就完事, 比如:

mvn archetype:create -DgroupId=example -DartifactId=demo -DarchetypeArtifactId=tellurium-junit-archetype -DarchetypeGroupId=tellurium -DarchetypeVersion=1.0-SNAPSHOT  -DarchetypeRepository=http://kungfuters.org/nexus/content/repositories/snapshots

这个命令创建了Tellurium JUnit 测试项目。然后用编辑器如IntelliJ IDEA打开项目用如下部步骤,

New Project > Import project from external model > Maven > Project directory > Finish

你会发现项目中有以下文件

pom.xml
src
src/main
src/main/groovy
src/main/resources
src/test
src/test/groovy
src/test/groovy/module
src/test/groovy/module/GoogleSearchModule.groovy
src/test/groovy/test
src/test/groovy/test/GoogleSearchTestCase.java
src/test/resources
TelluriumConfig.groovy

其 中TelluriumConfig.groovy是Tellurium配置文件, 而GoogleSearchModule是示范网页模块文件, 而GoogleSearchTestCase是示范测试文件。检查项目的Groovy配置,确保是1.6.0版本。 然后就可以用以下Maven命令来运行示范测试文件了,

mvn test

如果你想创建TestNG项目,可以用以下Maven命令:

mvn archetype:create -DgroupId=your_group_id -DartifactId=your_artifact_id -DarchetypeArtifactId=tellurium-testng-archetype -DarchetypeGroupId=tellurium -DarchetypeVersion=1.0-SNAPSHOT -DarchetypeRepository=http://kungfuters.org/nexus/content/repositories/snapshots

创建自己的UI模块

Tellurium的Firefox Plugin(TrUMP)可以用来自动创建网页模块文件, 然后你加入测试逻辑就行了。 TrUMP可以从Tellurium网站下载

http://code.google.com/p/aost/downloads/list

或者从Firefox addons直接下载

https://addons.mozilla.org/en-US/firefox/addon/11035

TrUMP简单易用,具体的操作这里就不细说了。

相关资源