[Flex]AsWing:Java开发者的ActionScript朋友?

mikel阅读(1063)

作者 Moxie Zhang译者 张龙 发布于 2009年3月1日 上午8时38分

社区
Java
主题
RIA
标签
ActionScript

长久以来Java Swing一直是Java开发者主要的图形界面构建包,那么Java Swing的经验和技巧能否用于构建基于ActionScript 3的RIA系统呢?AsWing Framework的目标就在于此。InfoQ有幸采访了AsWing的首席开发者iiley Chen以了解AsWing是如何有助于RIA开发的。

在被问到为何创建AsWing而不是使用其他的UI框架时,iiley Chen说到:

确实,Flex出现之前有很多很酷的框架,但大多数都不易使用并且功能不完全。很多框架都缺少一些重要的组件,如Tree、 DataGrid及强大的布局管理器等等。在2005年开发第一个大型应用(一个Flash做的在线社区)时,我需要一个强大的UI框架。我有Java Swing的经验并且喜欢Swing的架构和设计模式。但我坚信如果有一个类似于Swing的Flash UI框架的话,我可以快速且舒服的构建出应用的UI。因此我开始用ActionScript2语言开发AsWing并保持其大部分API与Swing一 致。现在AsWing已经基于ActionScript3了并且重新进行了设计,同时还多次进行了重构。一些家伙甚至告诉我它比Swing和Flex还要 好用。谢谢他们,他们让我觉得开发AsWing是件有意义的事。

关于AsWing的主要优势和特点,Chen说到:

主要优势在于你可以使用纯ActionScript编码轻松构建流式/动态的UI。AsWing的核心仅仅是一些易于操纵和管理的ActionScript类。如果你具有Java Swing经验,那么这些技巧也可以用到AsWing上。
AsWing提供了40多个现代的UI组件,包括专业的ColorMixiers和一些特别的组件,如JLabelButton、Form、Folder及GridList。
此外,凭借设计良好的MVC模式,你可以轻松将数据更新到UI视图上。就像Flex拥有数据绑定一样,AsWing也有各种数据模型,他们会自动通知视图进行更新。
其中的SkinBuilder工具可以帮助开发者创建完全不同的皮肤,所用的方式仅仅是提供一些组件图片或是Flash符号。除此之外,GuiBuilder有助于UI的布局设计并生成ActionScript源代码。
最后,AsWing不是重量级的。并不像其他的UI框架(他们也是应用框架),AsWing只关注于UI。你可以将AsWing与任何其他的应用框架组合起来使用。

就开发环境来说,AsWing非常灵活。Chen说到:

AsWing的开发没有什么特别之处。任何ActionScript开发环境都可以,比如说Flex Builder、FDT及FlashDevelop等等。AsWing仅仅是个项目中可以使用的ActionScript库。你可以使用Flex编译器或 是Flash编译器来编译AsWing应用。其中的GuiBuilder工具是个AIR应用,因此需要AIR运行时才能运行它。

就AsWing的路线图,Chen说到:

目前我正忙于AsWing2.0,这是个主版本。我们将用更好的方式重新设计其感官样式。最重要的新特性就是新的皮肤技术的引 入。你只需就倾斜度、色调、圆角或阴影属性编写几行代码就可以改变组件样式而无需开发复杂的ComponentUI类。同时我们还会增加一些新组件,如 Numeric Stepper、Date Chooser、Advanced TextArea及Advanced Table等等。

Chen给出了如下的Hello World AsWing应用代码:

package{
import flash.display.Sprite;
import org.aswing.*;
public class HelloWorld extends Sprite{
    public function HelloWorld(){
        AsWingManager.initAsStandard(this);
        JOptionPane.showMessageDialog("Title", "Hello World!");

    }
}
}

Java Swing开发者对此是不是很熟悉呢?

查看英文原文:AsWing, An ActionScript Fiend of Java Developers?

[Flex]FMS系列(一):第一个FMS程序,连接到FMS服务器(Flash/Flex两种实现)

mikel阅读(620)

FMS是个很牛X的东西,到底有多牛X我不想在这里多说,有兴趣的朋友可以baidu一把了解一下,如果实在是不想动手,那你就点下面的连接吧,我搜索了点资料简单的总结了一下。

    你可以点击这里了解一些关于FMS的基本知识: 了解一些FMS的基本概念

     通常做FMS都是和Flash或是Flex结合开发的,特别是在视频流这方面相当的突出,成功案例也不少,比如http://www.tudou.com,  www.ku6.com , http://www.15dv.com 等视频网站都与FMS挂钩。本人也是因为工作需要,趁工作之余来学习这门技术,想通过写博客的方式来巩固和分享学习,更希望爱好或是在从事这方面开发工作 的朋友多多指正,交流。OK,本文就以连接FMS服务器作为写作话题,来看看我们学习FMS应该从什么地方出发,逐步的走上更高的台阶。

     Adobe公司的产品Flash和Flex都可以结合FMS进行编程,本文示例比较简单,为了多凑几个字我打算通过Flash和Flex两种实现来介绍怎么来实现我们的第一个FMS程序“连接到FMS服务器”。

     上山砍柴不忘磨柴刀,那么我们做技术开发肯定也离不开对开发环境,开发工具,开发语言的选择和准备。本文中我们的工具就是Flash CS 4,Flex Builder 3和FMS 3.0,所使用的开发语言是ActionScript 3.0,这里我不想浪费时间去介绍软件的安装,相信看这篇文章的你对于安装软件不会存在有什么难度,OK,下面看看怎么编码实现。

一 、FMS应该做些什么 

     本文中所使用到的FMS是非常简单的,主要就就是建立一个FMS应用,方法很简单。找到你安装FMS的目录你会发现里面有一个 appliations的目录。对的,它就是管理FMS应用的目录,进入该目录在里面建立一个文件夹就OK,我建立的文件夹为"firstFMS"。

 

二、Flash连接到FMS服务器

     首先建立一个Flash文件(ActionScript 3.0)并将其保存在某个目录(自己决定吧)中。然后打开组件面板(可以按Ctrl+F7)从组件面板中拖拽一个button组件到刚建立好的Flash 的舞台(也就是Flash显示东西的那一块地方),然后通过属性面板(可以按Ctrl+F3)将刚拖拽出的button取个名字(Flash中叫他为实例 名,舞台中的每一个组件就是一相对应的对象的实例),我取的是btnConnFMS

     完成上面两步后回到舞台,鼠标在舞台中空白位置点击一下,然后同样打开属性面板,你会发现现在的属性面板和先前的有些不一样,在发布选项下找到“类”,这里我填写的为“ConnFMS”,表示我将要通过ConnFMS.as这个类文件来对当前的这个Flash进行编码。

     上面承诺了由ConnFMS.as来负责Flash的编码工作,那该怎么做呢?建立一个ActionScript类文件,保存在之前保存Flash文件的同一目录就OK,记住这个类文件一定是“ConnFMS.as”。下面是ConnFMS.as的完整代码:

 1 package
 2 {
 3     import flash.net.NetConnection;
 4     import flash.net.NetStream;
 5     import flash.display.MovieClip;
 6     import flash.net.Responder;
 7     import flash.events.MouseEvent;
 8     import flash.events.NetStatusEvent;
 9     import flash.events.AsyncErrorEvent;
10     
11     public class ConnFMS extends MovieClip
12     {
13         private var nc:NetConnection;
14         
15         public function ConnFMS()
16         {
17             btnConnFMS.label="连接到FMS";
18         }
19         
20         private function onClickHandler(evt:MouseEvent):void
21         {
22             trace("正在连接FMS服务器");
23             nc = new NetConnection();
24             nc.connect("rtmp://localhost/firstFMS");
25             nc.addEventListener(NetStatusEvent.NET_STATUS,onNetStatusHandler);
26         }
27         
28         private function onNetStatusHandler(evt:NetStatusEvent):void
29         {
30             switch (evt.info.code)
31             {
32                 case "NetConnection.Connect.Success":
33                     trace("成功连接FMS服务器!");
34                     break;
35                 case "NetConnection.Connect.Rejected":
36                     trace ("访问FMS服务器权限不足,连接被拒绝!");
37                     break;
38                 case "NetConnection.Connect.InvalidApp":
39                     trace("指定的应用程序名称没有找到");
40                     break;
41                 case "NetConnection.Connect.Failed":
42                     trace("连接失败!");
43                     break;
44                 case "NetConnection.Connect.AppShutDown":
45                     trace("服务器端应用程序已经关闭(由于资源耗用过大等原因)或者服务器已经关闭!");
46                     break;
47                 case "NetConnection.Connect.Closed":
48                     trace("与FMS的连接中断!");
49                     break;
50             }
51         }
52     }
53 }

 

 三、Flex连接到FMS服务器

     首先建立好Flex项目,默认会创建一个MXML文件,简单化实现这里就直接在这个MXML文件里来实现连接FMS。代码上和Flash连接到FMS几乎没有什么差别,主要就是学习NetConnection类来完成,如下代码定义:

1 //Flex与FMS建立连接的对象
2 private var netConn:NetConnection;
3 //FMS服务器的地址,使用rtmp协议
4 private var rtmpUrl:String="rtmp://localhost/firstFMS"; 

 

   NetConnection指示 Flash Player 是通过持久性的 RTMP 连接连接到服务器,实现这一步操作是通过NetConnection类的connect()方法来完成的。如下:

1 //当Flex应用程序启动的时候就建立与FMS服务器的连接
2 internal function onInit():void
3 {
4     netConn = new NetConnection();
5     netConn.connect(rtmpUrl);
6     netConn.addEventListener(NetStatusEvent.NET_STATUS,onNetStatusHandler);
7     netConn.addEventListener(AsyncErrorEvent.ASYNC_ERROR,onAsyncErrorHandler);
8 }   

 

  connect()方法打开指定rtmp协议地址的FMS服务器的连接。一旦调用该方法NetConnection的对象就会捕捉到FMS返回的一个网络连接状态,通过NetStatusEvent事件监听可以得到返回状态的值(详细见本文前Flash部分),AsyncErrorEvent事件为异步引发异常(既本机异步代码)时调度。关于NetConnection的各种状态的详细请查看本文之前的Flash实例有详细的介绍。

   由于实例比较简单,这里我就不在多说废话,下面是通过Flex实现连接到FMS的完整代码:

 1<?xml version="1.0" encoding="utf-8"?>
 2<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
 3    <mx:Script>
 4        <![CDATA[
 5            import mx.controls.Alert;
 6            //Flex与FMS建立连接的对象
 7            private var nc:NetConnection;
 8            //FMS服务器的地址,使用rtmp协议
 9            private var rtmpUrl:String="rtmp://localhost/firstFMS";
10            
11            //当Flex应用程序启动的时候就建立与FMS服务器的连接
12            internal function onClick():void
13            {
14                nc = new NetConnection();
15                nc.connect(rtmpUrl);
16                nc.addEventListener(NetStatusEvent.NET_STATUS,onNetStatusHandler);
17                nc.addEventListener(AsyncErrorEvent.ASYNC_ERROR,onAsyncErrorHandler);
18            }

19            
20            private function onClickHandler(evt:MouseEvent):void
21            {
22                trace("正在连接FMS服务器");
23                nc = new NetConnection();
24                nc.connect("rtmp://localhost/firstFMS");
25                nc.client=this;
26                nc.addEventListener(NetStatusEvent.NET_STATUS,onNetStatusHandler);
27                nc.addEventListener(AsyncErrorEvent.ASYNC_ERROR,onAsyncErrorHandler);
28            }

29        
30            private function onNetStatusHandler(evt:NetStatusEvent):void
31            {
32                switch (evt.info.code)
33                {
34                    case "NetConnection.Connect.Success":
35                        trace("成功连接FMS服务器!");
36                        break;
37                    case "NetConnection.Connect.Rejected":
38                        trace ("访问FMS服务器权限不足,连接被拒绝!");
39                        break;
40                    case "NetConnection.Connect.InvalidApp":
41                        trace("指定的应用程序名称没有找到");
42                        break;
43                    case "NetConnection.Connect.Failed":
44                        trace("连接失败!");
45                        break;
46                    case "NetConnection.Connect.AppShutDown":
47                        trace("服务器端应用程序已经关闭(由于资源耗用过大等原因)或者服务器已经关闭!");
48                        break;
49                    case "NetConnection.Connect.Closed":
50                        trace("与FMS的连接中断!");
51                        break;
52                }

53            }

54            
55            private function onAsyncErrorHandler(evt:AsyncErrorEvent):void
56            {}
57    ]]>
58    </mx:Script>
59    <mx:Button x="135" y="89" label="Button" click="onClick()" fontSize="12" fontWeight="normal"/>
60</mx:Application>

 

   

四、注意事项

  通常新手在学习FMS的时候都会遇到一个问题,那就是通过NetConnection连接FMS服务器的时候,连接状态总是返回 “NetConnection.Connect.Rejected”这样的状态结果,然后接着还有会有一个 “NetConnection.Connect.Failed”状态,是什么原因造成这样的错误的呢?

  第一个错误从本文实例中你可以得到,是访问FMS服务器的权限问题,如果FMS没有开设足够的访问权限,通常在访问FMS的客户端都会接受到这 样一个异常状态。第二个错误又是怎么产生的呢?这还是又访问权限引起,当客户端没有主够的权限访问FMS服务器,就将返回 “NetConnection.Connect.Rejected”状态并自动断开与FMS服务器的连 接,“NetConnection.Connect.Failed”状态本身是由于连接服务器失败产生,而这里是因为权限问题而引发的。

  前几天很多朋友就在问我这个问题,怎么来解决这个问题呢?如果你是一个技术专研者,如果又你赶兴趣的技术在你面前,你首先会做什么?查看官方提 供的文档?实例代码?还是什么? OK,其实要解决这个问题很简单,在FMS服务器安装好后的目录下有一个"applications"目录,里面有两个FMS默认安装的FMS服务器 (live和vod),随便打开一个默认安装然后打开里面的"readme.txt"文件会看到下面的字样:

================================================================
Deploying an unsigned vod service
================================================================
    
1. Create a new folder in the {FMS-Install-Dir}/applications folder.
2. If you are replacing the default Adobe signed live service, back up
   the following files:
   * main.far
   * Application.xml
   * allowedHTMLDomains.txt
   * allowedSWFDomains.txt

3. Copy files from {FMS-Install-Dir}/samples/applications/vod to the directory you created in step 1.

 

  现在你知道怎么解决上面出现的问题了吗??将这main.far、Application.xml、 allowedHTMLDomains.txt和allowedSWFDomains.txt这四个文件复制到你创建的FMS服务器目录下就解决了,运行 上面的实例程序,然后可以通过FMS的管理控制台查看到详细的连接信息。

  我通常是使用的FMS安装目录下的fms_adminConsole.swf 来查看连接信息,也可以使用FMSfms_adminConsole.htm查看。

[C#]C#的Enum——枚举

mikel阅读(916)

枚举

  枚举类型声明为一组相关的符号常数定义了一个类型名称。枚举用于“多项选择”场合,就是程序运行时从编译时已经设定的固定数目的“选择”中做出决定。

  枚举类型(也称为枚举)为定义一组可以赋给变量的命名整数常量提供了一种有效的方法。例如,假设您必须定义一个变量,该变量的值表示一周中的一天。该变量只能存储七个有意义的值。若要定义这些值,可以使用枚举类型。枚举类型是使用 enum 关键字声明的。 

enum Days { Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday };

  默认情况下,枚举中每个元素的基础类型是 int。可以使用冒号指定另一种整数值类型。
  如果不为枚举数列表中的元素指定 值,则它们的值将以 1 为增量自动递增。在前面的示例中,Days.Sunday 的值为 0,Days.Monday 的值为 1,依此类推。创建新的 Days 对象时,如果不显式为其赋值,则它将具有默认值 Days.Sunday (0)。创建枚举时,应选择最合理的默认值并赋给它一个零值。这便使得只要在创建枚举时未为其显式赋值,则所创建的全部枚举都将具有该默认值。枚举中大小 写敏感,但是建议不要这样。

枚举的优点:
  <1>枚举可以使代码更易于维护,有助于确保给变量指定合法的、期望的值。
  <2>枚举使代码更清晰,允许用描述性的名称表示整数值,而不是用含义模糊的数来表示。
  <3>枚举使代码更易于键入。在给枚举类型的实例赋值时,VS.NET IDE会通过IntelliSense弹出一个包含可接受值的列表框,减少了按键次数,并能够让我们回忆起可能的值

枚举实例

  声明: 

public enum TimeOfDay
{
    Moning 
= 0,
    Afternoon 
= 1,
    Evening 
= 2,
};

  使用: 

    public string getTimeOfDay(TimeOfDay time)
    {
        
string result = string.Empty;
        
switch (time)
        {
            
case TimeOfDay.Moning:
                result 
= "上午";
                
break;
            
case TimeOfDay.Afternoon:
                result 
= "下午";
                
break;
            
case TimeOfDay.Evening:
                result 
= "晚上";
                
break;
            
default:
                result 
= "未知";
                
break;
        }
        
return result;
    }

 

枚举方法 

  <1>获取枚举字符串

TimeOfDay time = TimeOfDay.Afternoon;
Console.WriteLine(time.ToString());
//输出:Afternoon

 

  <2>Enum.Parse()方法。这个方法带3个参数,第一个参数是要使用的枚举类型。其语法是关键字typeof后跟放在括号中的枚举类名。typeof运算符将在第5章详细论述。第二个参数是要转换的字符串,第三个参数是一个bool,指定在进行转换时是否忽略大小写。最后,注意Enum.Parse()方法实际上返回一个对象引用—— 我们需要把这个字符串显式转换为需要的枚举类型(这是一个取消装箱操作的例子)。对于上面的代码,将返回1,作为一个对象,对应于TimeOfDay.Afternoon的枚举值。在显式转换为int时,会再次生成1。

TimeOfDay time2 = (TimeOfDay) Enum.Parse(typeof(TimeOfDay), "afternoon"true);
Console.WriteLine((
int)time2);//输出1

 

  <3>得到枚举的某一值对应的名称

lbOne.Text = Enum.GetName(typeof(TimeOfDay), 0);

    <4>得到枚举的所有的值 

foreach (int i in Enum.GetValues(typeof(TimeOfDay)))
            lbValues.Text 
+= i.ToString();

    <5>枚举所有的名称 

foreach(string temp in Enum.GetNames(typeof(TimeOfDay)))
            lbNames.Text
+=temp;

  

枚举和常量

  优先考虑枚举。

  在C#中,枚举的真正强大之处是它们在后台会实例化为派生于基类System.Enum的结构。这表示可以对它们调用方法,执行有用的任务。注 意因为.NET Framework的执行方式,在语法上把枚举当做结构是不会有性能损失的。实际上,一旦代码编译好,枚举就成为基本类型,与int和float类似。

  但是在实际应用中,你也许会发现,我们经常用英语定义枚举类型,因为开发工具本来就是英文开发的,美国人用起来,就直接能够明白枚举类型的含 义。其实,我们在开发的时候就多了一步操作,需要对枚举类型进行翻译。没办法,谁让编程语言是英语写的,如果是汉语写的,那我们也就不用翻译了,用起枚举 变得很方便了。举个简单的例子,TimeOfDay.Morning一看到Morning,美国人就知道是上午,但是对于中国的使用者来说,可能有很多人 就看不懂,这就需要我们进行翻译、解释,就向上面的getTimeOfDay()的方法,其实就是做了翻译工作。所以,在使用枚举的时候,感觉到并不是很 方便,有的时候我们还是比较乐意创建常量,然后在类中,声明一个集合来容纳常量和其意义。

  使用常量定义:这种方法固然可行,但是不能保证传入的参数day就是实际限定的。

using System;
using System.Collections.Generic;
public class TimesOfDay
{
    
public const int Morning = 0;
    
public const int Afternoon = 1;
    
public const int Evening = 2;
    
public static Dictionary<intstring> list;
    
/// <summary>
    
/// 获得星期几
    
/// </summary>
    
/// <param name="day"></param>
    
/// <returns></returns>
    public static string getTimeNameOfDay(int time)
    {
        
if (list == null || list.Count <= 0)
        {
            list 
= new Dictionary<intstring>();
            list.Add(Morning, 
"上午");
            list.Add(Afternoon, 
"下午");
            list.Add(Evening, 
"晚上");
        }
        
return list[time];
    }
}

 

希望能够找到一种比较好的方法,将枚举转为我们想要的集合。搜寻了半天终于找到了一些线索。通过反射,得到针对某一枚举类型的描述。

枚举的定义中加入描述 

using System;
using System.ComponentModel;
public enum TimeOfDay
{
    [Description(
"上午")]
    Moning,
    [Description(
"下午")]
    Afternoon,
    [Description(
"晚上")]
    Evening,
};

 

   获得值和表述的键值对

        /// <summary>
        
/// 从枚举类型和它的特性读出并返回一个键值对
        
/// </summary>
        
/// <param name="enumType">Type,该参数的格式为typeof(需要读的枚举类型)</param>
        
/// <returns>键值对</returns>
        public static NameValueCollection GetNVCFromEnumValue(Type enumType)
        {
            NameValueCollection nvc 
= new NameValueCollection();
            Type typeDescription 
= typeof(DescriptionAttribute);
            System.Reflection.FieldInfo[] fields 
= enumType.GetFields();
            
string strText = string.Empty;
            
string strValue = string.Empty;
            
foreach (FieldInfo field in fields)
            {
                
if (field.FieldType.IsEnum)
                {
                    strValue 
= ((int)enumType.InvokeMember(field.Name, BindingFlags.GetField, nullnullnull)).ToString();
                    
object[] arr = field.GetCustomAttributes(typeDescription, true);
                    
if (arr.Length > 0)
                    {
                        DescriptionAttribute aa 
= (DescriptionAttribute)arr[0];
                        strText 
= aa.Description;
                    }
                    
else
                    {
                        strText 
= field.Name;
                    }
                    nvc.Add(strText, strValue);
                }
            }
            
return nvc;
        }

 

[C#]Asp.net MVC:自定义的MVC Pager

mikel阅读(797)

实例懒得做。切几个图把代码发上要用的自己搞啦~

下面是一个helper类。


namespace System.Web.Mvc
{
    
public enum BarStyle
    
{
        yahoo, digg, meneame, flickr, sabrosus, scott, quotes, black, black2, grayr, yellow, jogger, starcraft2, tres, megas512, technorati, youtube, msdn, badoo, viciao, yahoo2, green_black
    }

    
public static class PagerBarExtension
    
{

        
public static string RenderPagerBar(this HtmlHelper html, int page, int total)
        
{
            
return RenderPagerBar(html, page, total, BarStyle.technorati);
        }


        
public static string RenderPagerBar(this HtmlHelper html, int page, int total, BarStyle style)
        
{
            
return RenderPagerBar(html, page, total, style, total);
        }


        
public static string RenderPagerBar(this HtmlHelper html, int page, int total, BarStyle style, int show)
        
{
            
if (total == 1)
            
{
                
return "";
            }

            
else
            
{
                StringBuilder sb 
= new StringBuilder();
                
string _path = html.ViewContext.HttpContext.Request.Path;
                sb.Append(
"<div class=\"");
                sb.Append(style.ToString());
                sb.Append(
"\" >");

                
string queryString = html.ViewContext.HttpContext.Request.QueryString.ToString();
                
if (queryString.IndexOf("page="< 0)
                
{
                    queryString 
+= "&page=" + page;
                }

                Regex re 
= new Regex(@"page=\d+", RegexOptions.IgnoreCase);
                
string result = re.Replace(queryString, "page={0}");

                
if (page != 1)
                
{
                    sb.AppendFormat(
"<span><a href=\"{0}\" title=\"第一页\">{1}</a></span>", _path + "?" + string.Format(result, 1), "<<");
                    sb.AppendFormat(
"<span><a href=\"{0}\" title=\"上一页\">{1}</a></span>", _path + "?" + string.Format(result, page  1), "<");
                }

                
if(page>(show+1))
                
{
                    sb.AppendFormat(
"<span><a href=\"{0}\" title=\"" + (show + 1) + "页\">{1}</a></span>", _path + "?" + string.Format(result,page(show + 1)), "..");

                }

                
for (int i = pageshow; i <= page+show; i++)
                
{
                    
if (i == page)
                    
{
                        sb.AppendFormat(
"<span class=\"current\">{0}</span>", i);
                    }

                    
else
                    
{
                        
if (i > 0 & i<=total)
                        
{
                            sb.AppendFormat(
"<span><a href=\"{0}\">{1}</a></span>", _path + "?" + string.Format(result, i), i);
                        }

                    }

                }

                
if (page < (total(show)))
                
{
                    sb.AppendFormat(
"<span><a href=\"{0}\" title=\"" + (show + 1) + "页\">{1}</a></span>", _path + "?" + string.Format(result, page + (show + 1)), "..");

                }

                
if (page < total)
                
{
                    sb.AppendFormat(
"<span><a href=\"{0}\" title=\"下一页\">{1}</a></span>", _path + "?" + string.Format(result, page + 1), ">");
                    sb.AppendFormat(
"<span><a href=\"{0}\" title=\"最后一页\">{1}</a></span>", _path + "?" + string.Format(result, total), ">>");

                }

                sb.AppendFormat(
"<span class=\"current\">共{1}页</span>", page, total);
                sb.Append(
"</div>");
                
return sb.ToString();
            }

        }

    }

}

 

使用(VIEW):


<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %>

<asp:Content ID="indexHead" ContentPlaceHolderID="head" runat="server">
    
<title>Home Page</title>
    
<link href="/Content/pagecss.css" rel="stylesheet" type="text/css" />
</asp:Content>
    
<asp:Content ID="indexContent" ContentPlaceHolderID="MainContent" runat="server">
    
<%= Html.ActionLink("带其它参数","Index",new {s = "MVC"} )%>
    
<%= Html.ActionLink("带其它参数2","Index",new { cid = 3} )%>
    
<%= Html.ActionLink("带其它参数3","Index",new {s = "MVC" , cid = 5} )%>
    
    
<%= Html.RenderPagerBar(Convert.ToInt32(ViewData["Page"]),Convert.ToInt32(ViewData["Total"]))%>
    
<%= Html.RenderPagerBar(Convert.ToInt32(ViewData["Page"]),Convert.ToInt32(ViewData["Total"]),BarStyle.badoo )%>
    
<%= Html.RenderPagerBar(Convert.ToInt32(ViewData["Page"]),Convert.ToInt32(ViewData["Total"]),BarStyle.badoo,3 )%>
    
<%= Html.RenderPagerBar(Convert.ToInt32(ViewData["Page"]),Convert.ToInt32(ViewData["Total"]),BarStyle.black,4 )%>
    
<%= Html.RenderPagerBar(Convert.ToInt32(ViewData["Page"]),Convert.ToInt32(ViewData["Total"]),BarStyle.digg,5 )%>
    
<%= Html.RenderPagerBar(Convert.ToInt32(ViewData["Page"]),Convert.ToInt32(ViewData["Total"]),BarStyle.flickr,3 )%>
    
<%= Html.RenderPagerBar(Convert.ToInt32(ViewData["Page"]),Convert.ToInt32(ViewData["Total"]),BarStyle.grayr,3 )%>
    
</asp:Content>

最后一个int参数表示显示当前页左右各多少个页码

 效果:

 

controller:

 


        public ActionResult Index(int? page,string s,int? cid)
        {
            int _page = page??1;
            ViewData["Message"] = "Welcome to ASP.NET MVC!";
            ViewData["Page"] = _page;
            ViewData["Total"] = 20;

            return View();
        }

 

不是啥高深的东西,不过蛮实用,

计算总页数和skip啥的就自己搞啦。给宝宝换尿布了

实例下载:/Files/francis67/MvcPagerDemo.rar

环境:VS2008SP1 ,ASP.NET MVC RC1

[C#]Asp.Net Mvc: Implement your custom ModelBinder

mikel阅读(808)

环境:

Windows 2008, VS 2008 SP1, ASP.NET Mvc RC1

——————————————————————————

上文:ASP.NET Mvc: Model Binding 机制分析  中,我们简单分析了ASP.NET MVC中Model Binding的过程,非常粗糙,本文将探索如何实现一个自己的ModelBinder,并进一步展示前文忽略的若干细节。

假设,我们现在有一个Book类,

现在我们要实现添加Book的功能,因此,新建一个BookController,并且加入一个Action:

建立相应的View:


其 实,到这一步,当我们提交表单的时候,在Action里面已经可以获得Book自动绑定,这归功于内建的DefaultModelBinder。但是,我 们基于某种考虑,想要使用自己创建的ModelBinder。于是,我们接着创建一个SimpleModelBinder类,该类实现了 IModelBinder接口(自定义的ModelBinder必须实现这个接口)。
IModelBinder只有一个方法BindModel(),这个方法接受两个参数:ControllerContext, ModelBindingContext,因此,我们在实现这个方法的时候,便需要好好利用这两个参数包含的信息。

现在来看SimpleModelBinder的具体实现:


上 面,我尽量避免硬编码,因为我希望这个SimpleModelBinder具有一定的通用性。此外也避免Model字段名称更改的连锁反应。这里,我们通 过bindingContext.ModelType来创建一个Model实例,通过TypeDescriptor来获取Model的Property集 合,通过bindingContext.ValueProvider来取得Request的表单信息,最后返回一个Model实例。

这样,我们的SimpleModelBinder就创建完了。那么,如何让它开始工作呢?

于是就引出一个问题:ASP.NET MVC如何确定当前需要应用哪个ModelBinder?

答案是:按先后顺序:(1)Action方法中Model的参数的Attribute,(2) ModelBinders.Binders字典,(3) Model类的Attribute,(4) DefaultModelBinder

也就是说,我们有(1)(2)(3)三种方法来告诉Asp.Net Mvc当前我们期望应用哪个ModelBinder到哪个Model。

(1) 在Action的Model参数上加Attribute:


(2) 将SimpleModelBinder添加到ModelBinders.Binders字典中:


(3) 在Book类定义时加上Attribute:


好啦,三个方法任由你选择。

这里,我们创建了一个很简单的自定义的ModelBinder,但你是否知道它至少还缺失了一个很重要的功能,就是绑定时对Model的 Property的过滤,因为一直以来我都把BindAttribute这个成员给忽视了。下篇,我们就来谈谈BindAttribute,并对 SimpleModelBinder做稍稍的完善。

此外,DefaultModelBinder很强大了,什么时候需要应用自定义的ModelBinder,则需要在实际项目中慢慢琢磨。 

Copyright

作者: Tristan G
本文版权归作者和博客园共有,欢迎转载 🙂

[Erlang]进入Erlang的世界

mikel阅读(1039)

原创作者: litaocheng  

进入Erlang的世界

作为程序员,我们曾经闻听很多“业界动态”,“技术革新”,曾经接触很多“高手箴言”,“权威推荐”。这些正确与否,都已成过去!

现在,让我们迎接Erlang盛宴!

经历

200711月在koders.com搜索代码时,发现*.erl格式的源文件,感叹开发语言的花样百出,此时,我觉得erlang是一个丑陋的小家伙,看名字就没有对它提起多少兴趣。

2008年初的时候,公司的项目开发中,我有缘认识了ejabberd,一个采用Erlang开发的开源jabber服务器。我开始为其诱人的特性所倾倒。是时候认真看看Erlang到底什么样了!

20084月,通过各种资料的搜集,了解,我决定系统的学习Erlang

今天,通过4个月的认真学习,我已经熟悉了Erlang,已经在使用Erlang开发项目。作为C++程序员,我不敢妄自使用“熟悉”,“精通”之类的字眼,但是对于Erlang我可以很负责任的说,Erlang很巧,很强大!

困惑

面对一个新的事务,我们本性都会充满好奇,可是作为程序员,很多时候对于新的语言我都充满了抵触:这个新东西值得学习么?它会不会让我抛弃我的旧爱?它文档丰富么?其是不是很难理解?它的前景如何?…等等,相信大家跟我有一样的苦恼。

但是,请听我说!我们是程序员,我们走在技术革新的最前沿。用户的产品,体验是通过我们来产生!我们不能畏缩不前,我们的固步自封,就是我们的公司,乃至整个我们的行业的停滞不前!口号可能有些响亮,但是认真思考,我相信朋友们一定有所感悟。

Erlang是什么

Erlang是什么是我们最先要面对的问题,只有清楚了它是什么,我们才能做出我们的决定。可见这个问题的重要性,它决定了很多读者是否会继续看下去!非常紧张。

Erlang最初是爱立信为开发电信相关产品而产生。

Erlang是一种面向并发(Concurrency oriented),面向消息(Message oriented)的函数式(Functional)编程语言。

面向并发说明Erlang支持大规模的并发应用,我们可以在应用中处理成千上万的并发,而不相互影响。面向消息,其实是为并发服务!我们应该都熟悉多线程,熟悉加锁解锁操作,熟悉可能出现的资源竞赛与死锁。在Erlang的世界里,我们可以将轻轻的抹去这些令人苦恼的词汇。Erlang的世界,每个处理都是独立的个体,他们之间的交互仅仅靠消息!因此不会有死锁,不会有痛苦的编程经历。

Erlang中一个非常重要的名词:Process,也就是我们前面提到的“个体”。它不是我们操作系统中的进程,也不是线程。它是Erlang提供给我们的超级轻量的进程。为了适应大规模并发的特性,Process需要能够快速创建,快速销毁。Process之间通信的唯一方法就是消息,我们只要知道一个Process的名字即pid,就可以向其发送消息。Process也可以在任何时候,接收消息。我们这样做只有一个目的:让我们的系统更加简单,用一种朴素的做法,实现一个高效的语言。

Erlang是种函数式编程语言,对此我没有很深刻的理解,最明显的特征就是,Erlang中到处都是函数,函数构成了我们的产品的主体,把这些函数放到一个个的Process中去,让他们运行起来,那么就组成了我们朝气蓬勃的产品。

Erlang支持对数据的位操作,拥有丰富的数据持久化机制。

同时需要说明的是Erlang内建垃圾回收机制(GC)。

Erlang语言特性

简单小巧

Erlang中只有8种基本的数据类型:

Integerfloatatomreferencefunportpidbitstring

同时提供2种复合结构:tuplelist,这就是Erlang的所有数据类型。

模式匹配

Erlang的函数中,某些语法中,我们可以使用Pattern匹配,这是一个非常好的特性,我们可以让代码自己去决定如何执行

比如,我们定义一个函数,其告诉我们某种水果的价格:

price(apple) -> 2.0;

price(banana) -> 1.2.

我们随后调用 price(Fruit),会根据Fruit变量的内容返回具体的价格。这样做的好处就是节省了我们的代码量,我们不用if…else…或者switch…case的来伺候了。也便于代码的扩展:加一个新的水果品种,我们只需要加一行就可以了。

学习Erlang一个非常重要的内容就是模式匹配,但是请不要混淆,这个匹配和正则表达式没有任何干系。

变量单次赋值

这个是一个匪夷所思的特性,变量竟然只能单次赋值!是的Erlang中变量一旦绑定某个数值以后,就不能再次绑定,这样做的好处是便于调试出错。当发生错误时,某个变量是什么就永远是什么,不用顺藤摸瓜的查找谁修改过它,省了好多事情。唯一的麻烦就是需要一个信的变量时,你必须再为它想一个名字。

丰富的libs

Erlang中提供丰富的libs

stdlib中包含大量的数据结构如listsarraydictgb_setsgb_treesetsdets

mnesia提供一个分布式的数据库系统

inets提供ftp clienthttp client/servertftp client/server

crypto 提供加密解密相关函数,基于openssl相关实现

ssl 实现加密socket通信,基于openssl实现

ssh 实现ssh协议

xmerl 实现XML相关解析

snmp 实现SNMP协议(Simple Network Management Protocol

observer 用来分析与追踪分布式应用

odbc 使Erlang可以连接基于SQL的数据库

orber 实现CORBA对象请求代理服务

os_mon 提供对操作系统的监控功能

dialyzer提供一个静态的代码或程序分析工具

edoc 依据源文件生成文档

gs 可以为我们提供某些GUI的功能(基于Tcl/Tk

还有很多朋友提供了一些开源的lib,比如eunit,用来进行单元测试。

灵活多样的错误处理

Erlang最初为电信产品的开发,这样的目的,决定了其对错误处理的严格要求。Erlang中提供一般语言所提供的exceptioncatchtry…catch等语法,同时Erlang支持LinkMonitor两种机制,我们可以将Process连接起来,让他们组成一个整体,某个Process出错,或推出时,其他Process都具有得知其推出的能力。而Monitor顾名思义,可以用来监控某个Process,判断其是否退出或出错。所有的这些Erlang都提供内在支持,我们快速的开发坚固的产品,不在是奢望。

代码热替换

你的产品想不间断的更新么?Erlang可以满足你这个需求,Erlang会在运行时自动将旧的模块进行替换。一切都静悄悄。

天生的分布式

Erlang天生适合分布式应用开发,其很多的BIF(内建函数,相API)都具有分布式版本,我们可以通过BIF在远程机器上创建Process,可以向远程机器上的某个Process发送消息。在分布式应用的开发中,我们可以像CC++,JAVA等语言一样,通过Socket进行通讯,也可以使用Erlang内嵌的基于Cookie的分布式架构,进行开发。当然也可以两者混合。分布式开发更加方便,快速。ErlangProcess的操作,Error的处理等都对支持分布式操作。

超强的并发性

由于采用其自身Process,而没有采用操作系统的进程和线程,我们可以创建大规模的并发处理,同时还简化了我们的编程复杂度。我们可以通过几十行代码实现一个并发的TCP服务器,这在其他语言中都想都不敢想!

多核支持

Erlang让您的应用支持多个处理器,您不需要为不同的硬件系统做不同的开发。采用Erlang将最大限度的发挥你的机器性能。

跨平台

如同JAVA一样,Erlang支持跨平台(其目前支持linuxmacwindows19种平台),不用为代码的移植而头疼。

我们仅仅需要了解平台的一些特性,对运行时进行优化。

开源

开源是我非常喜欢的一个词汇,开源意味这更加强壮,更加公开,更加的追求平等。开源会让Erlang更好。

Erlang与外界的交互

Erlang可以与其他的语言进行交互,如CC++,Java。当然也有热心的朋友提供了与其他语言的交互,如果需要你也可以根据Erlang的数据格式,提供一个库,让Erang与您心爱的语言交互。

Erlang支持分布式开发,您可以创建一个C Node,其如同一个Erlang节点,前提是你遵照Erlang的规范。

当然最常用的交互还是再同一个Node上,比如我们要调用某个lib,调用一些系统提供的功能,这时候主要有两种方式:Port和嵌入式执行。

PortErlang最基本的与外界交互的方式,进行交互的双方通过编码,解码,将信息以字节流的方式进行传递。(具体这个通道的实现方式,根据操作系统的不同而不同,比如unix环境下,采用PIPE实现,理论上任何支持对应Port通道实现的语言都可以与Erlang进行交互)。Erlang为了方便CJAVA程序员,提供了Erl_InterfaceJinterface

采用Port,您的代码在Erlang的平台之外运行,其崩溃不会影响Erlang

嵌入式执行,通过Erlang平台加载,因此这是非常危险的,如果您的程序崩溃,没有任何理由,Erlang也会崩溃。

Erlang应用场景

分布式产品,网络服务器,客户端,等各种应用环境。

Erlang也可以作为一种快速开发语言,进行原型开发。

Erlang的学习过程

1.         安装首先从Erlang官方网站,下载安装Erlanghttp://www.erlang.org/download.html

linux:获取源代码,根据说明编译;windows:直接安装

2.         认真阅读《programming erlang》(中文版图书已经问世),并不断动手练习书中的例程。

3.         遇到问题时,不要退却,坚持下去找到解决办法

4.         对语言熟悉时,浏览一些好的开源项目

5.         有信心时,开始动手做一个小项目

6.         不间断的与大家交流,共同提高

可能遇到的困难:

a)         对于语法的不适应?

坚持看下去,代码继续写下去,我相信1个月,你会喜欢上Erlang的语法

b)        有些数据类型不清楚?

认真看资料,或者询问朋友,比如我

c)        中文资料的缺乏?

Erlang中文的资料会越来越多,此外,Erlang的相关的英文资料也比较容易理解,还是那句话,别怕麻烦

Erlang开源项目

排名不分先后

  • couchdb     基于文档的数据库,拥有RestfulAPI,MVCC,View,诸多特性
  • ejabberd    性能出众,使用广泛的Jabber开源服务器
  • mochiweb    轻便,高效的HTTP应用框架
  • nitrogen    基于事件的Web开发框架
  • rabbitmq    中间服务器,实现AMQP协议
  • yaws        高效的web server
  • etorrent    Bittorrent客户端
  • Scalaris           分布式的key-value存储
  • disco       Map-Reduce框架,Erlang Python

遇到问题

参看Erlang官方文档 http://www.erlang.org/doc/

订阅Erlangmaillisthttp://www.erlang.org/mailman/listinfo/erlang-questions),进行提问

Nabble提供的Erlang maillist存档中搜索(http://www.nabble.com/Erlang-f14095.html

Google中搜索答案

推荐阅读

Erlang Design Principles http://www.erlang.org/doc/design_principles/part_frame.html

Erlang Efficiency Guide http://www.erlang.org/doc/efficiency_guide/part_frame.html

Erlang Programming Rules http://www.erlang.se/doc/programming_rules.shtml

推荐网站

http://www.erlang.org

http://erlang-china.org

http://www.planeterlang.org/

http://www.erlangplanet.org/

http://trapexit.org

[C#]再接再厉VS 2008 sp1 + .NET 3.5 sp1系列文章索引

mikel阅读(719)

[源码下载]

再接再厉VS 2008 sp1 + .NET 3.5 sp1系列文章索引

作者:webabcd
介绍
再接再厉VS 2008 sp1 + .NET 3.5 sp1系列文章索引:ADO.NET Entity Framework(实体框架), ADO.NET Data Services(数据服务), Dynamic Data(动态数据)
1、再接再厉VS 2008 sp1 + .NET 3.5 sp1(1) – Entity Framework(实体框架)之添加、查询、更新和删除的Demo
介绍
以Northwind为示例数据库,ADO.NET Entity Framework之完全面向对象的添加操作、查询操作、更新操作和删除操作

  • ADO.NET Entity Framework(EF) – 就当是微软的ORM吧,可以将概念模型映射到逻辑模型,从而使用概念模型做开发
  • Entity – 在EF中就是实体的概念
  • Entity Data Model(EDM) – 实体数据模型,表现为一组映射到数据源的实体和关系
  • LINQ to Entities – 和LINQ to XXX一样,对EF中的实体做LINQ
  • Entity SQL(ESQL) – 一种类似sql的查询语言,针对概念模型做查询
  • csdl – Conceptual schema definition language 概念架构定义语言
  • ssdl – Store schema definition language 存储架构定义语言
  • msl – Mapping specification language 映射规范语言
  • csdl, ssdl, msl均为基于XML的语言。.edmx文件同时包含这3种语言所描述的信息
  • Entity – 实体
  • Entity Class – 实体类。至少要有一个实体键(Key Properties)
  • Entity Set – 实体集。实体集中包含着若干实体
  • Association – 关联。实体类之间的关系。导航属性就是由关联来定义的
  • Association Set – 关联集。关联集中包含着若干关联
  • Entity Container – 实体容器。实体容器中包含着若干实体集和关联集
  • 概念模型中必须要有实体键,实体键与表中的主键相对应,所以表中必须要有主键
  • 存储模型的字段如果有主键键或非空约束,则概念模型中必需要有相应的属性与之映射
  • 概念模型中存在的属性,必须在存储模型中有与之映射的字段
  • 作为映射条件的字段不能映射到属性上
  • 要实现继承的话,就要使用映射条件来进行筛选
  • EntityConnection – 与存储模型的连接。相当于SqlConnection
  • EntityCommand – 对 EDM 执行的命令。相当于SqlCommand
  • EntityDataReader – 以只读、只进的数据流的方式获取数据(内存中始终只有一行)。相当于SqlDataReader

2、再接再厉VS 2008 sp1 + .NET 3.5 sp1(2) – Entity Framework(实体框架)之详解 Linq To Entities 之一
介绍
以Northwind为示例数据库,ADO.NET Entity Framework之Linq To Entities

  • First – 返回集合中的第一个成员;不延迟
  • FirstOrDefault – 返回集合中的第一个成员(找不到则返回null);不延迟
  • All – 是否集合中所有成员都满足某一条件;不延迟
  • Any – 集合中是否有成员满足某一条件;不延迟
  • Average – 取平均值;不延迟
  • Sum – 求和;不延迟
  • Max – 取最大值;不延迟
  • Min – 取最小值;不延迟
  • Count – 取指定集合的成员数,返回值类型int;不延迟
  • LongCount – 取指定集合的成员数,返回值类型long;不延迟
  • Take – 获取集合的前 n 个成员;延迟
  • Skip – 跳过集合的前 n 个成员;延迟(Linq To Entities 需要先排序才能 Skip)
  • Distinct – 过滤集合中的相同项;延迟
  • Union – 连接不同集合,自动过滤相同项;延迟
  • UnionAll – 连接不同集合,不会自动过滤相同项;延迟
  • Concat – 连接不同集合,不会自动过滤相同项;延迟
  • Intersect – 获取不同集合的相同项(交集);延迟
  • Except – 从某集合中删除其与另一个集合中相同的项;延迟

3、再接再厉VS 2008 sp1 + .NET 3.5 sp1(3) – Entity Framework(实体框架)之详解 Linq To Entities 之二
介绍
以Northwind为示例数据库,ADO.NET Entity Framework之Linq To Entities

  • Select – 选择需要返回的字段
  • Where – 筛选
  • OrderBy – 正序排序
  • OrderByDescending – 倒序排序
  • ThenBy – 在 orderBy 或 orderByDescending 的基础上再正序排序
  • ThenByDescending – 在 orderBy 或 orderByDescending 的基础上再倒序排序
  • GroupBy – 分组
  • Join – 连接
  • GroupJoin – 连接后分组

4、再接再厉VS 2008 sp1 + .NET 3.5 sp1(4) – Entity Framework(实体框架)之EntityClient, ObjectQuery
介绍
以Northwind为示例数据库,ADO.NET Entity Framework之详解EntityClient, ObjectQuery

  • EntityConnection – 与存储模型的连接
  • EntityCommand – 对 EDM 执行的命令
  • EntityParameter – 配置 EntityCommand 的参数
  • EntityDataReader – 以只读、只进的数据流的方式获取数据(内存中始终只有一行)。相当于SqlDataReader
  • ObjectQuery<T> – 通过 Entity SQL 或 查询语法 或 Linq 方法对概念模型做查询
  • ObjectContext.CreateQuery<T>(Entity SQL) – 根据 esql 创建一个 ObjectQuery<T> 。(延迟)

5、再接再厉VS 2008 sp1 + .NET 3.5 sp1(5) – Entity Framework(实体框架)之ObjectContext
介绍
以Northwind为示例数据库,ADO.NET Entity Framework之详解ObjectContext, 以及事务和并发

  • ObjectContext – 以对象(这些对象是 EDM 中定义的实体类型的实例)的形式与数据进行交互
  • CreateObjectName – 实体类 的 CreateObjectName 静态方法用于创建实体类的新实例
  • AddToEntitySetName() – 将需要添加的对象添加到对象上下文中
  • SaveChanges() – 将所有更新保存到相关存储区中
  • Attach()/AttachTo() – 附加外部实体到上下文中
  • ObjectContext.Refresh() – 更新上下文数据
  • ObjectStateEntry – 维护实体状态的类
  • ObjectStateManager – 实体状态管理器

6、再接再厉VS 2008 sp1 + .NET 3.5 sp1(6) – Entity Framework(实体框架)之Entity SQL
介绍
以Northwind为示例数据库,ADO.NET Entity Framework之详解Entity SQL

  • Linq 方法上也可以使用 esql
  • 查询表达式
    • select, from, where, order by, group by, having
    • cross join, inner join, left outer join, right outer join, full outer join
    • case when then else end
  • 集合运算符
    • anyelement(expression) – 从集合中提取任意元素
    • except – 从左侧表达式的结果中删除其与右侧表达式结果中的相同项,并返回此结果
    • flatten(collection) – 将多个集合组成的集合转换为一个集合
    • intersect – 返回运算符两侧查询结果的相同项
    • [not] exists(expression) – 确定查询结果是否存在
    • [not] in {,} – 确定某值是否在某集合中
    • overlaps – 确定运算符两侧查询结果是否具有相同项
    • set(expression) – 移除重复项
    • union – 将运算符两侧查询结果连接成一个集合(移除重复项)
    • union all – 将运算符两侧查询结果连接成一个集合(包括重复项)
    • top(n) – 取前 n 条记录
  • 分页运算符
    • skip n – 需要跳过的项数,结合 order by 使用
    • limit n – 需要选择的项数,结合 order by 使用
  • 类型运算符
    • cast(expression as data_type) – 将表达式转换为另一种数据类型(使用 EntityCommand 执行查询,返回 EDM 类型;使用 ObjectQuery 执行查询,返回 CLR 类型)
    • oftype – 从查询表达式返回指定类型的对象集合,需 EDM 中继承关系的支持
    • is of – 确定表达式的类型是否为指定类型或指定类型的某个子类型,需 EDM 中继承关系的支持
    • treat – 将指定基类型的对象视为指定派生类型的对象,需 EDM 中继承关系的支持
  • 常用运算符
    • 算术运算符
      • +
      • -(减或负)
      • *
      • /
      • %
    • 比效运算符
      • >, >=, <, <=, <>, !=
      • is null, is not null
      • between and, not between and
      • like, not like
    • 通配符(应用于 like 和 not like)
      • % – 零个或零个以上的任意字符
      • _ – 任意单个字符
      • [] – 在指定范围 [a-f] 或集合 [abcdef] 中的任意单个字符
      • [^] – 不在指定范围 [^a-f] 或集合 [^abcdef] 中的任意单个字符
    • 逻辑运算符
      • and, &&
      • or, ||
      • not, !
    • 其他字符
      • — – 注释
      • . – 成员访问
      • ; – 分行
      • + – 串联字符串
  • 函数
    • 函数 – 聚合函数
      • Avg(expression) – 非 null 的平均值
      • Count(expression) – 记录总数(Int64)
      • BigCount(expression) – 记录总数(Int32)
      • Max(expression) – 非 null 的最大值
      • Min(expression) – 非 null 的最小值
      • Sum(expression) – 非 null 的总和值
      • StDev(expression) – 非 null 的标准偏差值(相对于平均值的标准偏差)
    • 函数 – 数学函数
      • Abs(value) – 取绝对值
      • Ceiling(value) – 取不小于参数的最小整数
      • Floor(value) – 取不大于参数的最大整数
      • Round(value) – 取参数的整数部分
    • 函数 – 字符串函数
      • Left(string, length) – 从左侧开始,取 string 的前 length 个字符
      • Right( tring, length) – 从右侧开始,取 string 的前 length 个字符
      • LTrim(string) – 去掉 string 的左侧的空白
      • RTrim(string) – 去掉 string 的右侧的空白
      • Trim(string) – 去掉 string 的两侧的空白
      • ToLower(string) – 将 string 全部转换为小写
      • ToUpper(string) – 将 string 全部转换为大写
      • Concat(string1, string2) – 串联 string1 和 string2
      • Replace(string1, string2, string3) – 将 string1 中的所有 string2 都替换为 string3
      • Reverse(string) – 取 string 的反序
      • Substring(string, start, length) – 从 string 的 start 位置开始取 length 个字符,索引从 1 开始
      • IndexOf(string1, string2) – string1 在 string2 中的位置,索引从 1 开始,若找不到则返回 0
    • 函数 – 日期和时间函数
      • Year(expression) – 取时间的年的部分
      • Month(expression) – 取时间的月的部分
      • Day(expression) – 取时间的日的部分
      • Hour(expression) – 取时间的时的部分
      • Minute(expression) – 取时间的分的部分
      • Second(expression) – 取时间的秒的部分
      • Millisecond(expression) – 取时间的毫秒的部分(0 – 999)
      • CurrentDateTime() – 取服务器的当前时间
      • CurrentUtcDateTime() – 取服务器的 UTC 当前时间
      • CurrentDateTimeOffset() – 返回值类型为 DateTimeOffset , 取当前时间及相对于 UTC 时间的差值
    • 函数 – 按 位 运算的函数
      • BitWiseAnd(value1, value2) – 取 value1 和 value2 的位与结果
      • BitWiSEOr(value1, value2) – 取 value1 和 value2 的位或结果
      • BitWiseXor(value1, value2) – 取 value1 和 value2 的位异或结果
      • BitWiseNot(value) – 取 value 的位求反结果
    • 函数 – 其它函数
      • NewGuid() – 返回新生成的 GUID
  • 不常用运算符
    • row, multiset, createref, deref, key, ref, navigate

7、再接再厉VS 2008 sp1 + .NET 3.5 sp1(7) – Data Services(数据服务)
介绍
以Northwind为示例数据库,演示ADO.NET Data Services(数据服务)

  • DataService – ADO.NET 数据服务的主入口点。 T 为数据源类名
  • IDataServiceConfiguration.SetEntitySetAccessRule(string name, EntitySetRights rights) – 为指定实体集设置访问规则
  • QueryInterceptorAttribute – 声明在方法上的查询拦截器
  • DataServiceContext – 数据服务的上下文
  • DataServiceQuery – 以指定的 URI 语法查询数据服务

8、再接再厉VS 2008 sp1 + .NET 3.5 sp1(8) – Dynamic Data(动态数据)
介绍
以Northwind为示例数据库,演示Dynamic Data(动态数据)

  • MetaModel – 数据库和域对象之间的映射的抽象
  • MetaModel.RegisterContext() – 使用指定的配置上下文注册指定的数据上下文
  • Scaffold – 译为基架。即基于数据库架构(linq to sql 或 entity framework)生成网页模板的机制
  • ScaffoldTableAttribute(false) – 隐藏指定的表
  • ScaffoldColumn(false) – 隐藏指定的字段
  • MetadataTypeAttribute(Type metadataClassType) – 指定要与数据模型类关联的元数据类
  • DynamicField – 显示指定的动态数据字段,相当于 BoundField
  • DynamicControl – 通过指定的字段模板显示指定的动态数据字段

OK
[源码下载]

[C#]关于两个MVC示例的思考(MVCStore和Oxite)

mikel阅读(848)

      最近看了一些关于MVC框架的东西,加以之前就研究过一些关于 MVC架构的信息,碰巧在网上又看
到了这样一篇文章,是关于微软内部的开发者对Oxite项目的个人攻击,让我产生了写篇文章来表达一 
下自己对于这种架构模式的思考。
    声明,如果之前没看过这两个项目的朋友建议下载相应的源码:
    MVCStore:http://www.codeplex.com/mvcsamples
    Oxite:http://www.codeplex.com/oxite
    好了,开始今天的正文:)
1.Controller干了些什么
     先说一下我的看法,这个所谓控制器的最大作用应该是“控制和调度”,控制即前台视图(view)的
显示(显示那个视图), 调度即执行相应的业务逻辑 (在这两个项目中就是那些Services,而Services
即完成对model数据模型的封装调用,并实现相关的业务逻辑)。这里业务规则如何定义应该是在Ser-
vices里进行,与Controller无关。
     就其工作性质而言还是比较简单的,因此简要的工作内容就应该有简单的实现(指代码),这里可以
看看MVCStore是如何搞的,请见下面代码:
  (摘自Commerce.MVC.Web"App"Controller"AuthenticationController.cs):

public class AuthenticationController : Controller
{
        .
        
public ActionResult Login()
        {
            
string oldUserName = this.GetUserName();
            
string login = Request.Form["login"];
            
string password = Request.Form["password"];
            
if (!String.IsNullOrEmpty(login) && !String.IsNullOrEmpty(password))
            {
                var svc 
= new AspNetAuthenticationService();
                
bool isValid = svc.IsValidLogin(login, password);
                
//log them in
                if (isValid)
                {
                    SetPersonalizationCookie(login, login);
                    
//migrate the current order
                    _orderService.MigrateCurrentOrder(oldUserName, login);
                    
return AuthAndRedirect(login);
                }
            }
            
return View();
        }
    
}

     一看便知这是一个登陆验证操作,其使用Request.Form方式从表单中获取数据,这里暂不说其获取的方式
优不优雅(因为与本文要聊的内容关系不大)。可以看出其实现的过程也之前采用webform方式开发出现的代码
也差不多,只不过是将相应的login.aspx.cs中的操作放到这controller中,这种好处主要就是将原本分散但功
能上应该同属于认证的类(Authentication类是按架构设时划分出来的)放置在了一起,这样在代码分布上会
更合理一些。另外就是进行单元测试时也会很容易编写测试代码。当然还有好处,我想就是将那些经常变化的
代码使用这种方式约束在了controller中,为将来的后续开发,特别是维护以及查找BUG上会有一个比较清晰的
范围。
     当然在看Oxite代码时,这块会有所差异,即Oxite使用了IModelBinder来实现将表单中的数据绑定到相应
的类上以完成Model中(实体)类的初始化绑定工作,如下:

public class UserModelBinder : IModelBinder
{
    
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        NameValueCollection form 
= controllerContext.HttpContext.Request.Form;
        User user 
= null;
        Guid siteID 
= Guid.Empty;
        
if (!string.IsNullOrEmpty(form["siteID"]))
        {
            form[
"siteID"].GuidTryParse(out siteID);
        }
        
if (siteID == Guid.Empty)
        {
            user 
= new User
            {
                Name 
= form["userName"],
                Email 
= form["userEmail"],
                DisplayName 
= form["userDisplayName"],
                Password 
= form["userPassword"]
            };
            Guid userID;
            
if (!string.IsNullOrEmpty(form["userID"]) && form["userID"].GuidTryParse(out userID))
            {
                user.ID 
= userID;
            }
        }
        
return user;
    }
}

     其实这种做法有一定的好处,就是将这类在功能上类似的操作进行了封装。比如大家可以想像通过web请求提交过来
一个大表单,上面有几十个字段属性(不要问我为什么会有这种大表单),而如何将这些字段绑定的操作与controller中
接下来的业务流程操作放在一起,会让controller中的相应方法代码长度增长过快,所以倒不如通过上面这个方法将相应
的实体类与Web页面信息的绑定工作分离出来,当然 Oxite使用声明相应UserModelBinder类的方式进行封装的做法还
有待商榷
     说来说去,还是如Rob Conery所说的,要始终保持用Controller与View的轻快,易于测试这一原则。这一点其实正
与SOA架构中的一些思想相符合,下面结合我的理解来解释一下:
     在SOA中,有组件(component)的概念,即组件是业务逻辑的原子级功能操作,其按照高内聚低耦合的方式进行设计,
当业务流程开发运作时,其工作原理就是正确组合相应的业务组件来实现相应的应用。这样的好处就是可以将这些组件分
布式布署,同时当业务流程发生变化时,只要调整相应的业务流程逻辑(soa中称为bpel)即能够快速响应业务变化。而
如何构造这种可重用的组件在SOA中也是有相应规范的,被称为SCA.
     说到这里有些远了,那在MVC架构中又有什么类似的思想呢?其实在这里controller的一些设计要求与SOA中的bpel
有着相似的设计理念,即完成对业务组件(即MVCStore解决方案中的Commerce.Services项目下的相应文件)的流程
编排和调用。这样即便将来需求变化,而导致了业务流程的变化(不是业务规则变化),也只是修改Controller这一层应
该可以满足了,而正确而快速的修改的“前提”,应该就是该Controller应该设计得“尽可能的轻快”。
 
2.需求变化了,导致了业务规则变化怎么办?
   
     正如Ivar jacbson 在传授“明智开发”模型时所说的那样,“软件开发中不变的是–需求的不断变化”。这一点相信
大家是有强烈共鸣的。
     这里我们先来简单的看一下MVCStore和Oxite的处理方式,从设计思路上两个项目基本一致,即使用接口分离方式来
应对这种变化。比如:Oxite"Services"中就有这样的代码:

public class UserService : IUserService
{
      
private readonly IUserRepository repository;
      
private readonly IValidationService validator;
      
public UserService(IUserRepository repository, IValidationService validator)
      {
          
this.repository = repository;
          
this.validator = validator;
      }
      
#region IUserService Members
      
public User GetUser(string name)
      {
          
return repository.GetUser(name);
      }
      
public User GetUser(string name, string password)
      {
          User user 
= string.Compare(name, "Anonymous"true!= 0 ? repository.GetUser(name) : null;
          
if (user != null && user.Password == saltAndHash(password, user.PasswordSalt))
              
return user;
          
return null;
      }
      
public void AddUser(User user, out ValidationStateDictionary validationState, out User newUser)
      {
          validationState 
= new ValidationStateDictionary();
          validationState.Add(
typeof(User), validator.Validate(user));
          
if (!validationState.IsValid)
          {
              newUser 
= null;
              
return;
          }
       .
}

      其实现了IUserService服务接口。
      而MVCStore中的Commerce.Services项目中的代码也使用了类似接口定义,比如:

[Serializable]
public class OrderService : Commerce.Services.IOrderService {
    IOrderRepository _orderRepository;
    ICatalogRepository _catalogRepository;
    IShippingRepository _shippingRepository;
    IShippingService _shippingService;
    
public OrderService() { }
    
public OrderService(IOrderRepository rep, ICatalogRepository catalog,
        IShippingRepository shippingRepository, IShippingService shippingService)
    {
        _orderRepository 
= rep;
        _catalogRepository 
= catalog;
        _shippingRepository 
= shippingRepository;
        _shippingService 
= shippingService;
    }
    
/// <summary>
    
/// Gets all orders in the system
    
/// </summary>
    
/// <returns></returns>
    public IList<Order> GetOrders() {
        
return _orderRepository.GetOrders().ToList();
    }
 .
}

     定义并实现这些服务接口之后,就可以通过IOC这类方式来实现最终的注入,以决定在程序运行时使用那些具体
实现类了,比如Oxite中的Oxite/ContainerFactory.cs是这样进行注册的(使用了Unity框架):

public IUnityContainer GetOxiteContainer()
{
     IUnityContainer parentContainer 
= new UnityContainer();
     parentContainer
         .RegisterInstance(
new AppSettingsHelper(ConfigurationManager.AppSettings))
         .RegisterInstance(RouteTable.Routes)
         .RegisterInstance(HostingEnvironment.VirtualPathProvider)
         .RegisterInstance(
"RegisterRoutesHandler"typeof(MvcRouteHandler));
     
foreach (ConnectionStringSettings connectionString in ConfigurationManager.ConnectionStrings)
     {
         parentContainer.RegisterInstance(connectionString.Name, connectionString.ConnectionString);
     }
     parentContainer
         .RegisterType
<ISiteService, SiteService>()
         .RegisterType
<IPluginService, PluginService>()
         .RegisterType
<IUserService, UserService>()
         .RegisterType
<ITagService, TagService>()
         .RegisterType
<IPostService, PostService>()
         .RegisterType
<ITrackbackOutboundService, TrackbackOutboundService>()
     ..
}

    当然这种做法是有普遍性的,好处也是很明显。就是将来如果业务规则变化时(对应service接口实现类
也要发生变化),这时不需要真正修改已有的代码,只需再开发一个相应的实现类即可满足需求,这种扩展
方式也是与设计模式中的思想相符合的。
    说到这里,把话题再深入一下,就是微软模式与实践小组的Service Layer Guidelines中对象这块还会
有一个Application Facade(在其Business层中),如下图:
   
     其完成的是对这些service组件的“应用层面级”封装,说的再白一些,其可以包括对业务工作流,业务
实体,业务组件的三者的封装。以便于对外实现(暴露)统一的服务访问接口。就这部分而言,MVCStore
做的比Oxiete要好,其在工作流中对各类已定义的服务组件的逻辑调用写的很有味道,比如Commerce.-
Services项目下的 AcceptPayPalWorkflow.csShipOrderWorkflow.cs
     当然就目前工作流的作用远不止这些,必定其也可以采用WCF服务的方式把自己暴露给外界。就这一
点,其自身也可以转化为一个服务组件,到这里就出现了一个有趣的现象,即:
     已将一些服务组件囊括的工作流自己也成了一个服务组件而被其它服务组件所调用。不是吗?
     在SOA架构中,这种情况是很普遍的,因为组件是一些基本的业务规则逻辑,其应允许被其它组件访问
甚至包含以使业务规则更加清晰,说白了就是可复用性。
   
     对开发者而言只有这样才可能提升开发速度(重用已有组件的好处不仅仅是少写代码,还包括测试和布
署等方面的成本也会降低),这一点想一想那些开源的框架就会理解了。而对于企业管理者而言就是保护“
已有投资”

3.两个项目中的困惑

   
     的确,看了这两个MVC之后,还是有些让我感觉不是太清晰的地方,比如MVCStore中,Commerce.Data
项目下的Model/Order.cs类,我刚开始一看,还真被震住了,很有充血模型的味,下面是部分代码:

Code

     可正当我带着兴趣去观察其它相应的域模型类时,又回到了贫血域模型。不是吗?的方法是要感觉好像
不是一个开发人员写的才会出现这种情况,因为按其架构设计上来看,这个类中被放到Serivce中实现的,
因为我不是该项目的开发人员,想不出个所以然来。
     白乎了这些,其它在这两个项目中还有一些差异,当然本文开头提到的那篇文章也说出了一些“问题”。
不过还是那句话,没有最好的设计只有最适合的设计,这两个项目都有可圈可点的地方,但对自己所在公
司部门是不是“完全适合”只能结合自己团队的情况而定了。
     比如说关于Commerce.MVC.Web中将controller和view放在了一起,就是个问题,比如在团队中
有如下分工:
     VIEW开发人员 + Controller开发人员 + Service组件开发
     那么将View目录与Controller目录放在不同的项目中应该是个不错的方式,起码在项目级别上将这
两类开发者进行了分离。当然有人会说,一般情况下VIEW 和Controller的设计者应该是一个人而不是
两个人, 但分工明确才能尽一步提升生产力,特别是MVC这个框架还很新,有些开发人员学习是从View
语法入手,有些人从Controller入手,有些人比如我是从Service入手。这就导致关注和侧重点不同,最
后导致自己的理解和优势也会不同。将View分离出来的好处在于发挥各自的优势,让前台开发人员可以
将精力放在与UI设计师交流设计实现,界面实现,js(目前是JQuery)封装调用等方面。相信随着项目
的不断扩大和开发人员的后续补充势必会造成这样的问题。
     好了,今天的内容就先到这里了。
     
    
     原文链接:http://www.cnblogs.com/daizhj/archive/2009/02/26/1398689.html
     作者: daizhj, 代震军
     Tags: soa,mvc,sca,bpel
     网址: http://daizhj.cnblogs.com

[JQuery]Rich IntelliSense for jQuery

mikel阅读(925)

Update: A new Hotfix is availble to complement this file.

A while back we updated VS2008 IntelliSense to not fail when referencing JQuery.  However, getting IntelliSense for chained calls and rich summary/parameter hints still required adding special comments to a few thousand lines of JQuery.  If you didn't have the time, you could download such a file from friendly members of the community such as James and Brennan.

As part of our new partnership with jQuery, yesterday we announced the availability of the official IntelliSense documentation file.  As you can see, our friends at JQuery have added a new download link for Visual Studio at http://docs.jquery.com/Downloading_jQuery#Download_jQuery.

image

You can also download the file directly from http://code.jquery.com/jquery-1.2.6-vsdoc.js.  As you might guess, this documentation file corresponds with the latest version of jQuery (which is currently 1.2.6).  While this file has a "js" extension, it's really just a documentation file.  You do not want to run this file in the browser.

How do I use this file (today)?

If you're inside an ASPX page, you will need to add the following lines of code into (normally) the head of your page:

image

Why do we have a server-side conditional statement?  IntelliSense disregards conditional statements of this type, and thus loads the "vsdoc" file (overriding the normal one).  At runtime the if (false) statement will ensure it this documentation file is not rendered (and executed) as script.  This trick allows the "switching" behavior you want.

If you're in a JavaScript file, use the normal file reference syntax to refer to the "vsdoc" file.

image

There's no need for tricks here since this comment is only meaningful to IntelliSense.

How do I use this file (in the near future)?

The ideal user experience should be one where you do not need special tricks as mentioned above.  Really, you shouldn't need to mention the "vsdoc" file name at all.  To that end, we plan on releasing a Hotfix that will enable this (stay tuned!).  Given normal references such as…

image image

…IntelliSense will opportunistically search for "jQuery-1.2.6-vsdoc.js" and load that file instead.  Generally, given script name "x", IntelliSense will opportunistically search for "x-vsdoc.js".  If not found, it will then search for "x.Debug.js".  You just need to make sure to place your "vsdoc" file next to the normal file.  Note, if you use jQuery-1.2.6.min.js, you may need to rename the file to match the search pattern.

What are the advantages of this file?

One unique benefit of the file we have released is that it supports and understands jQuery plug-ins.  For example, given the plug-in below…

image

…you would see "myplugin" show up in IntelliSense.

image

We've noticed a few plug-ins do not work, and commonly this is because there is an IntelliSense incompatibility issue with the plug-in itself (as opposed to the jQuery documentation file).

Hope this helps!

Jeff King
Program Manager
Visual Studio Web Tools

[JQuery]VSDoc for jQuery 1.3.2 插件公布

mikel阅读(918)

JQuery 1.3 was released a little over a month ago.  The 1.3 release adds exciting features such as selector performance improvements, "live events" where events can be bound to both current and future elements, and more.  Version 1.3.2 was released a few days ago and fixes some bugs include one involving selector performance in IE.

I just wanted to let everyone know that we now have VSDoc files for all of the 1.3 releases.  You can download them from the jQuery Downloads page

jquerycom

A refresher on how to use the file can be found here or here.  Here's one of the new functions in action…

jqueryedit

Hope this helps!

Jeff King
Program Manager
Visual Studio Web Tools