[应用]jimu:积木在线电脑

mikel阅读(912)

在网上看到了一个本土的 webOS :积木在线电脑 。它是一个基于 Flash 的应用,操作流畅,用户体验很好。功能也很强悍,内置了ZOHO提供的文档编辑功能和IM,还有一堆应用可以自主“安装”使用。

ijimu-screenshoot.png

我觉得我的网速不是很好,但是使用起来基本没有卡的感觉,也没有把浏览器拖慢,作为一个全 Flash 的应用,我觉得很不容易,他们真的是用心在做。这里帮忙宣传一下,表示支持。

BTW,现在它们好像还是内测阶段,想要体验的可以点击下面的链接获取邀请:

http://ijimu.cn/?register=true&inviteCode=7298b866-5ddf-4e29-af1c-7ec174cff86c

本文链接: http://www.zhuoqun.net/html/y2009/1215.html 转载请注明出处,谢谢。

[SQL]SQL Server 2008中的用户自定义表类型

mikel阅读(923)

目前的批量删除和批量更新,很是烦人,解决方案无非三种:

XML,SQL自定义函数split,和CLR实现split。这几种都比较烦人,代码很多,维护麻烦,很不爽。

现在SQL2008新增的一个功能,我也不知道中文名怎么翻译,暂且叫他表参数吧。

大家可以看看示例:

这个就是用户定义的表类型:

 

 

然后给他定义一个类型:

 


 ================================
 Create User-defined Table Type
 ================================
USE Test
GO
 Create the data type
Create TYPE dbo.MyType AS TABLE 
(
    col1 
int NOT NULL
    col2 
varchar(20NULL
    col3 
datetime NULL
    
PRIMARY KEY (col1)
)
GO

 

可以看到,生成的表类型的组成情况,并且居然可以给表类型建立索引,呵呵

 

这个是操作 表类型的脚本:

 


DECLARE @MyTable MyType
Insert INTO @MyTable(col1,col2,col3)
VALUES (1,'abc','1/1/2000'),
    (
2,'def','1/1/2001'),
    (
3,'ghi','1/1/2002'),
    (
4,'jkl','1/1/2003'),
    (
5,'mno','1/1/2004')
    
Select * FROM @MyTable 

 

 

下面演示如何将表参数作为一个存储过程参数传递,以及ADO.NET的代码

sql部分:

 


USE [Test]
GO
Create TABLE [dbo].[MyTable] (
    
[col1] [int] NOT NULL PRIMARY KEY,
    
[col2] [varchar](20NULL,
    
[col3] [datetime] NULL,
    
[UserID] [varchar] (20NOT NULL
    )    
GO
Create PROC usp_AddRowsToMyTable @MyTableParam MyType READONLY,
    
@UserID varchar(20AS
    
    
Insert INTO MyTable([col1],[col2],[col3],[UserID])
    
Select [col1],[col2],[col3],@UserID    
    
FROM @MyTableParam
    
GO

 

 

如何在sql中调用此存储过程:

 


DECLARE @MyTable MyType
Insert INTO @MyTable(col1,col2,col3)
VALUES (1,'abc','1/1/2000'),
    (
2,'def','1/1/2001'),
    (
3,'ghi','1/1/2002'),
    (
4,'jkl','1/1/2003'),
    (
5,'mno','1/1/2004')
EXEC usp_AddRowsToMyTable @MyTableParam = @MyTable@UserID = 'Kathi'
Select * FROM MyTable

 

其中还涉及到一个权限问题,需要执行以下代码:

 


GRANT EXECUTE ON TYPE::dbo.MyType TO TestUser;

 

从.net app那调用此存储过程:

 


'Create a local table
Dim table As New DataTable("temp")
Dim col1 As New DataColumn("col1", System.Type.GetType("System.Int32"))
Dim col2 As New DataColumn("col2", System.Type.GetType("System.String"))
Dim col3 As New DataColumn("col3", System.Type.GetType("System.DateTime"))
table.Columns.Add(col1)
table.Columns.Add(col2)
table.Columns.Add(col3)
        
'Populate the table
For i As Integer = 20 To 30
    
Dim vals(2As Object
    vals(
0= i
    vals(
1= Chr(i + 90)
    vals(
2= System.DateTime.Now
    table.Rows.Add(vals)
Next

 

 

 


'Create a command object that calls the stored proc
Dim command As New SqlCommand("usp_AddRowsToMyTable", conn)
command.CommandType = CommandType.StoredProcedure
'Create a parameter using the new type
Dim param As SqlParameter = command.Parameters.Add("@MyTableParam", SqlDbType.Structured)
command.Parameters.AddWithValue("@UserID""Kathi")

 

 


'Set the value of the parameter
param.Value = table
'Execute the query
command.ExecuteNonQuery()

 

详情可以参看:

http://www.sqlteam.com/article/sql-server-2008-table-valued-parameters

[SQL]SQL Server 2005中xml类型和函数的简单应用

mikel阅读(956)

大家都知道SQL Server 2005新增了xml字段类型,我们可以利用它来实现批量操作数据库的需要,减少应用程序频繁、反复的建立数据库连接的情况发生,比如批量删除,我们可以在应用程序中构建如下xml:

<Delete><ID>1</ID><ID>2</ID><ID>3</ID></Delete>

在数据库中可以通过下面的脚本获得这些ID:

Select 
        T.ID.value(
'.''int'As ID
From
        
@xmlParam.nodes('/Delete/ID'as T(ID)

运行结果如下:

将xml类型作为存储过程的参数,批量删除的存储过程如下:

Create Procedure pro_Batch_Delete
@xmlParam xml
As

Delete from 
    t_TableName 
Where ID in 
    (
Select 
        T.ID.value(
'.''int'As ID
    
From
        
@xmlParam.nodes('/Delete/ID'as T(ID))

大家也知道,DataSet中的数据可以直接序列化成xml,通过dataSet.GetXml(),我们可以将这个xml作为存储过程参数,实现稍微复杂的功能,比如批量插入数据,在数据库中怎样将这个xml转换为表呢,我们先看DataSet序列化的xml结构:

<DataSet>
  
<Table><ID>1</ID><Count>1</Count></Table>
  
<Table><ID>2</ID><Count>2</Count></Table>
  
<Table><ID>3</ID><Count>3</Count></Table>
</DataSet>

当然也可以包含多个表,这里我们以一个表举例,转换脚本如下:

Declare @Xml xml
Set @Xml = '
<DataSet>
  <Table><ID>1</ID><Count>1</Count></Table>
  <Table><ID>2</ID><Count>2</Count></Table>
  <Table><ID>3</ID><Count>3</Count></Table>
</DataSet>
'
Select 
    T2.ID.value(
'.''int'As ID, T3.[Count].value('.','int'As [Count]
From 
    (
Select  
        T.Records.query(
'ID'As ID, 
        T.Records.query(
'Count'As [Count]
    
From 
        
@Xml.nodes('/DataSet/Table'As T(Records)
    ) 
As T1
Cross Apply T1.ID.nodes('ID'As T2(ID)
Cross Apply T1.[Count].nodes('Count'As T3([Count])

执行此脚本,可以得到我们想要的表:

批量插入记录的存储过程如下:

Create Procedure pro_Batch_Insert
@xmlParam xml
As

Insert Into t_TableName (ID, [Count])
(
    
Select 
        T2.ID.value(
'.''int'As ID, T3.[Count].value('.','int'As [Count]
    
From 
        (
Select  
            T.Records.query(
'ID'As ID, 
            T.Records.query(
'Count'As [Count]
        
From 
            
@xmlParam.nodes('/DataSet/Table'As T(Records)
        ) 
As T1
    
Cross Apply T1.ID.nodes('ID'As T2(ID)
    
Cross Apply T1.[Count].nodes('Count'As T3([Count])
)

同样,可以实现批量update的功能,这里不具体列举了,实现核Insert是基本相同的。
这里只使用部分SQL2005关于xml几个谓词和函数,在MSDN中都有说明,还有其他更强大的功能等大家一起去发掘.

[资源]国外的模板素材网站

mikel阅读(668)

下面推荐这几个国外模板素材网站:(如果大家有更好希望不要吝啬,拿出来大家共同分享)

FreeCssTemplates(免费下载网页模板)   :http://www.freecsstemplates.org/ 

这个网站主要用于公开的,无需注册,而且分类清楚,页面简洁找东西很方便,但唯一的不足是东西有点少

FreeWebTemplates(免费网页模板):http://www.freewebtemplates.com/

分类很清晰,每个分类的模板我认为做的都很专业,下载就直接修改使用,而且重要这个网站常常更新最新的模板(应该可以看出这个公司的业务量不错)

TemplateMonster(模板怪物圈):http://www.templatemonster.com/

这个布局太过混乱了,但素材还不错,仅作参考

CoolHomePage(门户主页模板):http://www.coolhomepages.com/ 

DesignGalaxy:http://www.designgalaxy.net/  主要是一些模板设计爱好者聚集地方

AplusTemplates:http://www.aplustemplates.com/  

WebDesignHelper:http://www.webdesignhelper.co.uk/   

TemplateHeaven:http://www.templateheaven.com/ 

CoolTemplates:http://www.coolesttemplates.com/

[C#]从零开始学习ASP.NET MVC(一) 开天辟地入门篇

mikel阅读(680)

一.摘要

和自身水平有关, 我总喜欢写入门级别的文章.比如虽然做项目用过一个内部的MVC框架, 但是当看到ASP.NET MVC时我却还是不知道从哪里入手开始学习的好.于是我写下这篇入门级的系列文章,  将老赵(Jeffrey Zhao)的ASP.NET MVC系列视频课程学到的知识再理解和再消化, 让最笨的人也能跟着我学懂ASP.NET MVC

二.人物简介

本 文的很多资料都来自老赵 , Jeffrey Zhao. 此人相信不必我多说了吧, 高手,前辈,偶像, 对老赵的敬仰如滔滔江水连绵不绝, 如黄河泛滥一发不可收拾……(省下口水文字若干). 在我搜索有没有更简单并且系统的介绍ASP.NET MVC的资料时, 搜索到了老赵在Webcast上面的系列视频教程. 当然了高手的讲解都是比较全面的, 有时侯听了1小时, 真正理解的只有几句话.于是有了一边学习一边写此系列文章的想法.其中的知识都是从老赵的教程中学习到得.

三.Hello ASP.NET MVC

现在开始跟着我一步一步学习ASP.NET MVC.在什么都不知道之前, 还是让我们先下载一个ASP.NET MVC程序. 当看到程序运行后, 我的心才会踏实很多.

首先去ASP.NET MVC的官网看看:

http://www.asp.net/mvc/

这里我们可以下载ASP.NET MVC的安装文件.目前最新版本是RC1 (注:RC, 即Release Candidate版本, 是距离正式版最近的一个版本.一般要经历RC1,2,3后即推出正式版)

另外我们可以在CodePlex上获取源代码:

http://www.codeplex.com/aspnet

在官网上下载ASP.NET MVC安装文件, 一路回车完成安装. 启动VS2008 SP1(不是VS2008?不是SP1?作为一个专业的IT人士,水平可以菜,软件咱一定要用新的!去找个新版本吧!),点击新建,在Web中可以找到:

image

点击确定即创建了一个默认的MVC项目.同时还会创建一个测试项目. 这些我现在都不懂也不关注, 直接将Web项目中的default.aspx设置为启动页, 运行项目, 一个ASP.NET MVC的项目已经运行在我的电脑上了:

image

而且那个Home和About还能点击!虽然现在我什么都不懂, 不过看着能运行的实例, 心里就踏实多了!

四.学习MVC的概念

老赵的视频教程第一讲是"MVC模式与ASP.NET MVC框架概述".主要讲解MVC的概念.那么让我们先来学习概念.

我是如此理解MVC的:

我们现在的一个ASP.NET页面通常需要做这些事情:

1.获取一个页面需要的数据. 

2.在页面的Page_Load(页面加载)方法中为我们的页面控件绑定数据

3.浏览器显示页面

MVC即Model, View, Controller

Model就是我们1中获取的网页需要的数据

Controller就是我们获取数据,然后将数据绑定到页面控件的这个业务流程.不十分正确但是可以先这样理解: Controller就是我们的Page_Load方法逻辑.

View就是我们的aspx页面,注意这是一个不包含后台代码文件的aspx页面.(其实带有.asp.cs文件也不会有编译错误,但是这样写代码就违背了MVC的设计初衷)

下面这张图很好的概括了MVC的作用:

image

一 个URL请求, ASP.NET MVC引擎会分析这个URL要使用那个Controller, 这个Controller(实际上真正的方法是Controller的Action)从数据库或者其他数据源获取数据,通常这些数据是一个业务的模型类 (即MVC中的Model). Controller将Model对象传递给页面(即MVC中的View),  页面显示在浏览器上.(这一步是ViewEngine的功能, 我们一般的ASPX页面使用的是WebForm的ViewEngine,当然也可以替换.)

五.学习实例首页

简单的概念也有了.实例也能运行了.现在就是看看这个实例是如何使用ASP.NET MVC的.从首页下手.

1.寻找入口方法

首 页网站的地址应该是 http://localhost:1847/home/index , 为什么地址不是具体的页面但是最后却将请求提交给了view/home/Index.aspx 页面? 很明显是使用了URL重写. ASP.NET中叫做UrlRouting,对应的程序集是System.Web.Routing, 打开项目的Global.asax.cs文件, 会找到我们建立的页面重写规则:

        public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default",                                              // Route name
"{controller}/{action}/{id}",                           // URL with parameters
new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
);
}
protected void Application_Start()
{
RegisterRoutes(RouteTable.Routes);
}

 

 

关于Routing的深入了解将在以后介绍, 这里我们完全可以照葫芦画瓢, 按照实例添加新的重写规则.

最后, http://localhost:1847/home/index 就被解析为:

Controller为Home, Action为Index, 没有id参数.

2.寻找Controller

在Controllers文件夹下我们可以找到HomeController.cs, 这里使用了一个约定, 就是如果URL中获取到的Controller名字是Home, 则他的Controller类名就是HomeController. 在URL中的名字后加上”Controller”.

实例中Controller都放在Controllers文件夹, 所以我们可以按照命名约定很容易就可以找到HomeController类

3.寻扎Action

打开HomeControllers.cs, 发现里面有两个方法:

        public ActionResult Index()
{
ViewData["Message"] = "Welcome to ASP.NET MVC!";
return View();
}
public ActionResult About()
{
return View();
}

其中的Index和About都是Action.这个Action是个什么东东呢?目前我只知道一个Controller可以包含多个Action, MVC模式中Controller角色的具体实现逻辑都是在Action中的.

因为我们的Action是Index, 所以自然就要调用Index()方法.这里将"Webcome to ASP.NET MVC!", 这里的Model角色就是这句话, 也就是一个字符串对象.

Controller的一个重要作用就是将Model对象传递给View,也就是具体的页面. 传递的方法就是将这个字符串放到ViewData这个集合对象中, 然后在页面上也调用这个对象获取数据. 这个ViewData 对象一定是静态的, 或者至少是和HttpContext对象关联的, 否则到了View页面上是不能够调用的.但是也不知道ASP.NET MVC是在什么时候创建了这个对象.有心深入的一会去源代码里找找就能找到答案了.

4.寻找View

Model有了,数据有了, 接下来要跳转到View去显示数据了.第一个问题就是如何从Controller中跳到View上? return View() 这句话实现了此功能.其实如果这样写大家会更清楚:

        public ActionResult Index()
{
ViewData["Message"] = "Welcome to ASP.NET MVC!";
return View("index");
}

View方法中可以带一个名字, 这个名字就是View的名字.如果把index改成about,那么访问/home/index就会跳转到about页!

虽然知道了我们要返回到名称是"index"的View上, 但是这个View的页面在哪里呢?在Web中有一个Views文件夹:

image

这里面存放的都是View对象, 也就是只有显示功能的aspx页面文件.但是aspx文件要遵循约定: Views下面要按照Controller创建文件夹, 比如HomeController就对应Home文件夹, 然后在里面添加view, 比如index.aspx, 那么在HomeController中返回到名为Index的View对象实际就会返回Views/Home/Index.aspx页面.

如果不写View的名字, 则认为Action的名称就是View的名称.

5.页面展示

最后的工作就是View页面使用Model数据完整页面显示工作, 在index.aspx这个没有后台代码的View对象中, 通过ViewData对象获取Model:

<%= Html.Encode(ViewData["Message"]) %>

 

接下来ViewEngine即页面引擎会将aspx中的HTML部分以及上面的数据部分和在一起返回给浏览器.

关于View对象我注意到此页面是继承自System.Web.Mvc.ViewPage而不是直接继承自System.Web.UI.Page, 而这个ViewData对象就是ViewPage中的一个属性. 这里的ViewData一定是页面级别的,当页面编译完毕这个对象就会被注销(HTTP是无状态的协议,每次请求其实都是生成一个新的ViewPage对 象).

六.总结

虽然仅仅是第一篇入门文章, 但是是不是觉得已经会用ASP.NET MVC了? 虽然学习不可以骄傲, 但是可以自豪的是ASP.NET MVC我已经不再陌生, 即使不能驾轻就熟, 偶尔说出来几个概念,给你解释解释啥是MVC, 还是很能吓唬人的. 这篇文章相当于老赵前两篇视频的知识. 本着每日一篇的原则, 我将会继续学习老赵的系列教程,  将自己的理解贡献出来. 不求最深, 但求易懂.

[C#]从零开始学习ASP.NET MVC(二) 识别URL的Routing组件

mikel阅读(788)

一.摘要

本篇文章从基础到深入的介绍ASP.NET MVC中的Routing组件. Routing翻译过来是"路由选择", 负责ASP.NET MVC的第一个工作:识别URL, 将一个Url请求"路由"给Controller. 由于今天下午参加了博客园北京俱乐部的聚会, 所以本篇文章的完工时间晚了点, 还好也是在今天发表, 总算兑现了"每日一篇"的承诺. 不久丁学就会发布北京博客园聚会活动的资料了, 我在这里先预告了!

二.承上启下

第一篇文章中我们已经学会了如何使 用ASP.NET MVC, 虽然其中还有很多的细节没有深入了解, 但是对基本的处理流程已经有了认识:来了一个Url请求, 从中找到Controller和Action的值, 将请求传递给Controller处理. Controller获取Model数据对象, 并且将Model传递给View, 最后View负责呈现页面.

而Routing的作用就是负责分析Url, 从Url中识别参数, 如图:

image

这一讲就让我们细致的了解System.Web.Routing及其相关的扩展知识.

三.Routing的作用

第一讲中实例的首页地址是: localhost/home/index

我们发现访问上面的地址, 最后会传递给 HomeController中名为index的action(即HomeController类中的index方法).

当然服务器端不会自己去实现这个功能,  关键点就是在Global.asax.cs文件中的下列代码:

        public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default",                                              // Route name
"{controller}/{action}/{id}",                           // URL with parameters
new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
);
}
protected void Application_Start()
{
RegisterRoutes(RouteTable.Routes);
}

 

回来看我们的Url: localhost/home/index

localhost是域名, 所以首先要去掉域名部分: home/index

对应了上面代码中的这种URL结构: {controller}/{action}/{id}

因为我们建立了这种Url结构的识别规则, 所以能够识别出 Controller是home, action是index, id没有则为默认值"".

这就是Routing的第一个作用:

1.从Url中识别出数据.比如controller,action和各种参数.

如果跟踪程序, 接下来我们会跳转到HomeController中的Index()方法.  这是Routing内部为实现的第二个作用:

2.根据识别出来的数据, 将请求传递给Controller和Action.

但从实例中我们并不知道Routing如何做的这部份工作.第五部分我做了深入讲解.

四.Routing的使用

在分析Routing的实现原理前, 先学习如何使用Routing为ASP.NET MVC程序添加路由规则.

1. 使用MapRoute()方法.

这是最简单的为ASP.NET MVC添加识别规则的方法.此方法有如下重载:

MapRoute( string name, string url);
MapRoute( string name, string url, object defaults);
MapRoute( string name, string url, string[] namespaces);
MapRoute( string name, string url, object defaults, object constraints);
MapRoute( string name, string url, object defaults, string[] namespaces);
MapRoute( string name, string url, object defaults, object constraints, string[] namespaces);
 

name参数:

规则名称, 可以随意起名.当时不可以重名,否则会发生错误:
路由集合中已经存在名为“Default”的路由。路由名必须是唯一的。

url参数:

url获取数据的规则, 这里不是正则表达式,  将要识别的参数括起来即可, 比如: {controller}/{action}

最少只需要传递name和url参数就可以建立一条Routing(路由)规则.比如实例中的规则完全可以改为:

            routes.MapRoute(
"Default",
"{controller}/{action}");

defaults参数:

url参数的默认值.如果一个url只有controller: localhost/home/

而且我们只建立了一条url获取数据规则: {controller}/{action}

那么这时就会为action参数设置defaults参数中规定的默认值. defaults参数是Object类型,所以可以传递一个匿名类型来初始化默认值:

new { controller = "Home", action = "Index" }

实例中使用的是三个参数的MapRoute方法:

            routes.MapRoute(
"Default",                                              // Route name
"{controller}/{action}/{id}",                           // URL with parameters
new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
);

constraints参数:

用来限定每个参数的规则或Http请求的类型.constraints属性是一个RouteValueDictionary对象,也就是一个字典表, 但是这个字典表的值可以有两种:

  • 用于定义正则表达式的字符串。正则表达式不区分大小写。

  • 一个用于实现 IRouteConstraint 接口且包含 Match 方法的对象。

  • 通过使用正则表达式可以规定参数格式,比如controller参数只能为4位数字:

    new { controller = @"\d{4}"}
     

    通过第IRouteConstraint 接口目前可以限制请求的类型.因为System.Web.Routing中提供了HttpMethodConstraint类, 这个类实现了IRouteConstraint 接口. 我们可以通过为RouteValueDictionary字典对象添加键为"httpMethod", 值为一个HttpMethodConstraint对象来为路由规则添加HTTP 谓词的限制, 比如限制一条路由规则只能处理GET请求:

    httpMethod =  new HttpMethodConstraint(  "GET", "POST"  )
    

    完整的代码如下:

                routes.MapRoute(
    "Default",                                              // Route name
    "{controller}/{action}/{id}",                           // URL with parameters
    new { controller = "Home", action = "Index", id = "" },  // Parameter defaults
    new { controller = @"\d{4}" , httpMethod = new HttpMethodConstraint( "GET", "POST" ) }
    );

    当然我们也可以在外部先创建一个RouteValueDictionary对象在作为MapRoute的参数传入, 这只是语法问题.

    namespaces参数:

    此参数对应Route.DataTokens属性. 官方的解释是:

    获取或设置传递到路由处理程序但未用于确定该路由是否匹配 URL 模式的自定义值。

    我目前不知道如何使用. 请高手指点

    2.MapRoute方法实例

    下面通过实例来应用MapRoute方法. 对于一个网站,为了SEO友好,一个网址的URL层次不要超过三层:

    localhost/{频道}/{具体网页}

    其中域名第一层, 频道第二层, 那么最后的网页就只剩下最后一层了. 如果使用默认实例中的"{controller}/{action}/{其他参数}"的形式会影响网站SEO.

    假设我们的网站结构如下:

    image

    下面以酒店频道为例, 是我创建的Routing规则:

            public static void RegisterRoutes(RouteCollection routes)
    {
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    #region 酒店频道部分
    // hotels/list-beijing-100,200-3
    routes.MapRoute(
    "酒店列表页",
    "hotels/{action}-{city}-{price}-{star}",
    new { controller = "Hotel", action = "list", city = "beijing", price="-1,-1", star="-1" },
    new { city=@"[a-zA-Z]*",price=@"(\d)+\,(\d)+", star="[-1-5]"}
    );
    //hotels/所有匹配
    routes.MapRoute(
    "酒店首页",
    "hotels/{*values}",
    new { controller = "Hotel", action = "default", hotelid = "" }
    );
    #endregion
    //网站首页.
    routes.MapRoute(
    "网站首页",
    "{*values}",
    new { controller = "Home", action = "index"}
    );
    }
     

    实现的功能:

    (1)访问 localhost/hotels/list-beijing-100,200-3 会访问酒店频道的列表页,并传入查询参数

    (2)访问 localhost/hotels 下面的任何其他页面地址, 都会跳转到酒店首页.

    (3)访问 localhost 下面的任何地址, 如果未匹配上面2条, 则跳转到首页.

    简单总结:

    (1)Routing规则有顺序(按照添加是的顺序), 如果一个url匹配了多个Routing规则, 则按照第一个匹配的Routing规则执行.

    (2)由于上面的规则, 要将具体频道的具体页面放在最上方, 将频道首页 和 网站首页 放在最下方.

    (3) {*values} 表示后面可以使任意的格式.

    3.使用Route类

    MapRoute方法虽然简单, 但是他是本质也是通过创建Route类的实例, 为RouteCollection集合添加成员.

    下载最新版本的MSDN-Visual Studio 20008 SP1, 已经可以找到Route类的说明.

    创建一个Route类实例,最关键的是为以下几个属性赋值:

    属性名称 说明 举例
    Constraints 获取或设置为 URL 参数指定有效值的表达式的词典。 {controller}/{action}/{id}
    DataTokens 获取或设置传递到路由处理程序但未用于确定该路由是否匹配 URL 模式的自定义值。 new RouteValueDictionary { { "format", "short" } }
    Defaults 获取或设置要在 URL 不包含所有参数时使用的值。 new { controller = "Home", action = "Index", id = "" }
    RouteHandler 获取或设置处理路由请求的对象。 new MvcRouteHandler()
    Url 获取或设置路由的 URL 模式。 new { controller = @"[^\.]*" }

    这些属性除了RouteHandler以外, 其他的都对应MapRoute方法的参数.RouteHandler是实现了IRouteHandler接口的对象.关于此接口的作用在第五部分Routing深入解析中做讲解.

    五.Routing深入解析

    对于一个一般开发人员来说, 上面的知识已经完全足够你使用ASP.NET MVC时使用Routing了.

    接下来的部分我将深入Routing的机制讲解Routing的高级应用.但是因为是"高级应用", 加上这篇文章已经太长了, 再加上马上今天就过去了, "每日一篇"的承诺一定要兑现的, 所以不会对所有细节进行讲解. 或者也可以略过此部分.

    Routing如何将请求传递给Controller?上面讲解Routing作用的时候, 我们就分析出Routing会将请求传递给Controller, 但是Routing如何做的这部份工作我们却看不到.关键在于MapRoute()这个方法封装了具体的细节.

    虽然MapRoute方法是RouteCollection对象的方法,但是却被放置在System.Web.Mvc程序集中, 如果你的程序只引用了System.Web.Routing, 那么RouteCollection对象是不会有MapRoute方法的. 但是如果你同又引用了System.Web.Mvc, 则在mvc的dll中为RouteCollection对象添加了扩展方法:

           public static void IgnoreRoute(this RouteCollection routes, string url);
    public static void IgnoreRoute(this RouteCollection routes, string url, object constraints);
    public static Route MapRoute(this RouteCollection routes, string name, string url);
    public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults);
    public static Route MapRoute(this RouteCollection routes, string name, string url, string[] namespaces);
    public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, object constraints);
    public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, string[] namespaces);
    public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, object constraints, string[] namespaces);

    RouteCollection是一个集合,他的每一项应该是一个Route对象. 但是我们使用MapRoute时并没有创建这个对象, 这是因为当我们将MapRoute方法需要的参数传入时, 在方法内部会根据参数创建一个Route对象:

            public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, object constraints, string[] namespaces) {
    if (routes == null) {
    throw new ArgumentNullException("routes");
    }
    if (url == null) {
    throw new ArgumentNullException("url");
    }
    Route route = new Route(url, new MvcRouteHandler()) {
    Defaults = new RouteValueDictionary(defaults),
    Constraints = new RouteValueDictionary(constraints)
    };
    if ((namespaces != null) && (namespaces.Length > 0)) {
    route.DataTokens = new RouteValueDictionary();
    route.DataTokens["Namespaces"] = namespaces;
    }
    routes.Add(name, route);
    return route;
    }

    上面就是MapRoute方法的实现, 至于在创建Route对象时第二个参数是一个MvcRouteHandler, 它是一个实现了IRouteHandler接口的类. IRouteHandler十分简单只有一个方法:

    IHttpHandler GetHttpHandler(RequestContext requestContext);

    参数是一个RequestContext 类实例, 这个类的结构也很简单:

        public class RequestContext
    {
    public RequestContext(HttpContextBase httpContext, RouteData routeData);
    public HttpContextBase HttpContext { get; }
    public RouteData RouteData { get; }
    }

    其中的一个属性RouteData就包含了Routing根据Url识别出来各种参数的值, 其中就有Controller和Action的值.

    归根结底, ASP.NET MVC最后还是使用HttpHandler处理请求. ASP.NET MVC定义了自己的实现了IHttpHandler接口的Handler:MvcHandler,  因为MvcRouteHandler的GetHttpHandler方法最后返回的就是MvcHandler. 

    MvcHandler的构造函数需要传入RequestContext 对象, 也就是传入了所有的所有需要的数据, 所以最后可以找到对应的Controller和Action, 已经各种参数.

    六.测试Routing

    因为一个Url会匹配多个routing规则, 最后常常会遇到规则写错或者顺序不对的问题.于是我们希望能够看到Url匹配Routing的结果.

    其中最简单的办法就是使用RouteDebug辅助类. 这个类需要单独下载dll组件, 我将此组件的下载放在了博客园上:

    http://files.cnblogs.com/zhangziqiu/RouteDebug-Binary.zip

    解压缩后是一个DLL文件, 将这个DLL文件添加到项目中并且添加引用.

    使用方法很简单, 只需要在Application_Start方法中添加一句话:

    RouteDebug.RouteDebugger.RewriteRoutesForTesting(RouteTable.Routes);

    比如下面是我的示例中的代码:

            protected void Application_Start()
    {
    RegisterRoutes(RouteTable.Routes);
    RouteDebug.RouteDebugger.RewriteRoutesForTesting(RouteTable.Routes);
    }

    现在你访问任何URL, 都会出现RouteDebug页面, 如下:

    image

    其中不仅有你的所有Routing规则, 还显示了是否匹配.并且按照顺序列出. 还有识别的参数列表.

    当你不想测试Routing规则的时候则注释掉这一段, 即可回复跳转到View对象上.

    七.总结

    本文讲解了ASP.NET MVC中一个关键的组件:Routing的使用. System.Web.Routing在Framework3.5 SP1中已经集成, 也就是说虽然我们还没有ASP.NET MVC的正式版, 但是Routing组件却已经提早发布了. 因为Routing是一个相对独立的组件, 不仅能和ASP.NET MVC配额使用, 也可以用于任何需要URL路由的项目. 另外Routing的作用和Url重写(Url Rewrite)是有区别的, 你会发现Routing和Url Rewrite相比其实很麻烦, 无论是添加规则还是传递参数.对UrlRewite感兴趣的可以去寻找UrlRewrite.dll这个组件, 很简单很强大, 有关两者的异同以及如何使用UrlRewrite这里不在多说了.

    另外今天博客园北京俱乐部聚会, 听了2位大师的讲座, 见到了至今没记住名字和样子的同行们, 很是激动和兴奋. 期待俱乐部领导将活动照片和资料放出!

    本文的示例下载地址:

    http://files.cnblogs.com/zhangziqiu/Demo-2.rar

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

    mikel阅读(1119)

    作者 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阅读(642)

    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阅读(962)

    枚举

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

      枚举类型(也称为枚举)为定义一组可以赋给变量的命名整数常量提供了一种有效的方法。例如,假设您必须定义一个变量,该变量的值表示一周中的一天。该变量只能存储七个有意义的值。若要定义这些值,可以使用枚举类型。枚举类型是使用 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;
            }