下载:Creating Mashups with Adobe Flex and AIR
简介
Web applications no longer need be powered by any one individual's data, and they don't need to be confined to the desktop. Developers can draw on a wealth of publicly available content, from providers such as Flickr, Amazon, Google, Twitter, and Last.fm, and combine it for use in their own applications. Adobe Integrated Runtime (AIR) makes it simple to bring previously web-only applications to the desktop, allowing them to run alongside traditional applications on an end user's computer.
In this book, you'll learn how to create mashup applications from the vast array of web services, feeds, and APIs using Adobe Flash and Flex together with HTML and JavaScript (Ajax). You'll be introduced to the various sources of information and the tools necessary to gather and reuse that information, and then you'll learn how to combine that content in a variety of ways.
You'll learn how to have desktop applications interact with online services such as Flickr, you'll learn how to use Amazon S3 for enterprise-level data storage, and you'll embrace technologies such as OpenID. In addition, you'll create abstract visualizations based on music sourced from Last.fm and consume Twitter content via RSS. You will also see how to use the Flash-native data format SWX along with PHP to create a Yahoo! weather widget.
You'll discover just why you may want to build a widget or a desktop application rather leaving things web-based; then you'll create an application using Flex Builder and AIR and learn how best to distribute it. With so many tools and so much data available, the possibilities for mashup creation are endless. Creating Mashups with Adobe Flex and AIR provides all you need to get you up and running quickly, while also giving you a solid understanding of the technologies involved so you can take things further—to a place limited only by your imagination.
In this book you'll learn
* how to use Flex 3 in conjunction with ActionScript 3.0 to build powerful applications;
* how you can use Adobe AIR to take your application from the Web and onto the
desktop;
* the differences between developing for the Web and for the desktop;
* how you can use the APIs of popular web services such as Flickr, Amazon, Google, Twitter, and Last.fm as data sources for your application; and
* how to optimize your applications for fast and efficient performance.
目录 Summary of Contents
* Chapter 1 Introduction to Mashups
* Chapter 2 Technologies to Mash With!
* Chapter 3 An Introduction to Flex
* Chapter 4 Flex Components
* Chapter 5 Flexing Your Muscles
* Chapter 6 Performance Management in Flex Applications
* Chapter 7 Debugging Flex 3: The Tried-and-True, Plus the New
* Chapter 8 Getting the Most out of APIs
* Chapter 9 Mashing Up Functionality
* Chapter 10 SWX: A Native Flash Data Format
* Chapter 11 Taking It to the Desktop
* Chapter 12 Developing for the Desktop with AIR
* Chapter 13 Adding More Desktop Elements to the Web
* Chapter 14 Building a Desktop Experience
* Chapter 15 Completing the Experience
download: http://uploadstock.com//index.php?page=main&id=4c605910&name=Creating.Mashups.with.Adobe.Flex.and.AIR.rar
Password : knowfree.net
[资源]ASP.net控件字典
http://www.aspnextgen.com/quickstart/aspplus/doc/webcontrolsref.aspx
[教程]ASP.Net MVC的Html.ActionLink解析2
在《ASP.NET MVC框架配置与分析》这篇文章中,已经介绍了MVC框架的配置,并且简单讲述了它的运行机制。本文将重点描述,MVC框架中默认的地址重写。
1、注册地址重写
MVC的地址重写必须在Global.asax.cs中初始化,从而保证所有的请求都能被Controller控制。简单的意思就是必须在运行期,应用程 序启动的时候被初始化。为什么要到运行期,而不发生在编译器,为什么不能用静态构造函数来完成呢?那是因为编译期连地址都没确定,怎么能够保证地址是正确 的呢?
在Global.asax.cs中默认有两个重写方法被注册
2 {
3 // Note: Change Url= to Url="[controller].mvc/[action]/[id]" to enable
4 // automatic support on IIS6
5
6 RouteTable.Routes.Add(new Route
7 {
8 Url = "[controller]/[action]/[id]",
9 Defaults = new { action = "Index", id = (string)null } ,
10 RouteHandler = typeof(MvcRouteHandler)
11 });
12
13
14 RouteTable.Routes.Add(new Route
15 {
16 Url = "Default.aspx",
17 Defaults = new { controller = "Home", action = "Index", id = (string)null },
18 RouteHandler = typeof(MvcRouteHandler)
19 });
20
21
22 }
第一个注册方法是描述了一组规则,而第二组方法描述了根目录下的Default.aspx如何交由controller 来处理。
2、controller 处理地址
比如,我们现在的URL地址是www.yurow.cn,那么,当请求www.yurow.cn的时候,实际上是请求的Default.aspx,这个时候,程序找到规则Defaults = new { controller = "Home", action = "Index", id = (string)null },(这个是默认规则,所有的默认规则都可以通过Defaults = object的方式来调用,当然也有例外,下面会讲到。)。默认规则告诉程序,这个页面请求要交给一个类名为HomeController的控制器来处理(controller = "Home", 就是用控制器的类名减去Controller,这点和Attribute非常相似)。而action = "Index"告诉程序,请求的是控制器中的Index方法,最后的 id = (string)null 则是默认参数。在MVC中,默认参数只有一个,就是id。而这里id值是null。在默认HomeController类中也有两个方法
2 public void Index()
3 {
4 RenderView("Index");
5 }
6
7 [ControllerAction]
8 public void About()
9 {
10 RenderView("About");
11 }
请求Default.aspx调用Index方法后,将输出定位到Index.aspx(RenderView("Index");)。这时候显示的就是Index.aspx。当然,这时候浏览器显示的地址是http://www.yurow.cn/,实际上还可以有另外一种表示方式http://www.yurow.cn/Home/Index。
而“域名/controller/action/id” 才是MVC真正的地址现实方式。映射的地址则是“根路径 /Views/controller/action(.aspx)”。id参数不是交由aspx文件处理的,而是交由controller处理,这点我认 为就是和WebForm模型最大的不同。
再来看看注册的第一组规则: Url = "[controller]/[action]/[id]",定义了URL的路径就是上面所说的“域名/controller/action/id”,在这里就是http://www.yurow.cn/Home/About 。
3、controller 到View的数据传递
这两组定义中似乎都没有用到id参数,id到底体现在哪里呢?
尝试在HomeController和About.aspx.cs中接收id参数Request["id"],然后把地址变成http://www.yurow.cn/Home/About/1,结果Request["id"]是null并不是我们想象中的'1'。而事实上是这样接收这个id参数的:
public void About(string id)
{
if (string.IsNullOrEmpty(id))
id = "";
RenderView("About", (object)id);
}
在About.aspx.cs中要这样使用
2 {
3
4 protected void Page_Load(object sender, EventArgs e)
5 {
6 Response.Write(ViewData);
7 }
8 }
ViewPage< string>定义了About.aspx.cs接收Controller里传递过来的 (object)id,并且申明这是一个string类型。而ViewData就是这个值。当然也可以定义成任何类型,因为这里接收的类型是object。
4、重写后的地址构造
MVC提供了自动构造重写地址的方法——Html.ActionLink。
Html.ActionLink一共有3个重载。
1)先说简单的public string ActionLink(string linkText, string actionName);
参数一是链接显示的文字,而参数二是action的名称。比如Html.ActionLink("链接文字","About");
链接地址实际是< a href="/Home/About">链接文字< /a>。地址中的Home是怎么来的呢?就是Defaults里定义的。注意,如果你不去改写,那么赋值了一次,无论是controller 还是action或者id的值都是一直不变的。而这个Home在注册的时候就已经被赋值了。
2)public string ActionLink(string linkText, string actionName, string controllerName);
参数一和参数二和1)相同,参数三则是controller的名称。比如你可以赋值
Html.ActionLink("链接文字","MyPage","Test");
链接地址实际是< a href="/Test/MyPage">链接文字< /a>。明明没有Test控制器,也没有MyPage页面,怎么能够定义成功?这就是因为,虽然参数名是这样定义的,实际上这仅仅是一个字符串,代表要请求的目录(controllerName),和aspx文件(actionName)。
3)public string ActionLink(string linkText, object values);
这个是自定义式的赋值。可以这样写:
< %= Html.ActionLink("About Us", new { id="1",controller="Home", action="About" })%>
实际地址就是< a href="/Home/About/1">About Us"< /a>。
[教程]ASP.Net MVC的Html.ActionLink解析
Html.ActionLink 方法用于指向Controller的Action
ActionLink方法定义的代码
//页面显示linkText指向Global.asax.cs中默认的Controller对象的actionName方法
public string ActionLink(string linkText, string actionName) {
if (String.IsNullOrEmpty(linkText)) {
throw new ArgumentException(MvcResources.Common_NullOrEmpty, "linkText");
}
if (String.IsNullOrEmpty(actionName)) {
throw new ArgumentException(MvcResources.Common_NullOrEmpty, "actionName");
}
return GenerateLink(linkText, null /* routeName */, actionName, null /* controllerName */, new RouteValueDictionary());
}
//页面显示linkText指向默认Global.asax.cs中默认的Controller对象的actionName方法并且带的参数值values
public string ActionLink(string linkText, string actionName, object values) {
if (String.IsNullOrEmpty(linkText)) {
throw new ArgumentException(MvcResources.Common_NullOrEmpty, "linkText");
}
if (String.IsNullOrEmpty(actionName)) {
throw new ArgumentException(MvcResources.Common_NullOrEmpty, "actionName");
}
return GenerateLink(linkText, null /* routeName */, actionName, null /* controllerName */, new RouteValueDictionary(values));
}
//页面显示linkText指向定义的RouteValueDictionary中的Controller对象的actionName方法
public string ActionLink(string linkText, string actionName, RouteValueDictionary valuesDictionary) {
if (String.IsNullOrEmpty(linkText)) {
throw new ArgumentException(MvcResources.Common_NullOrEmpty, "linkText");
}
if (String.IsNullOrEmpty(actionName)) {
throw new ArgumentException(MvcResources.Common_NullOrEmpty, "actionName");
}
if (valuesDictionary == null) {
throw new ArgumentNullException("valuesDictionary");
}
return GenerateLink(linkText, null /* routeName */, actionName, null /* controllerName */, new RouteValueDictionary(valuesDictionary));
}
//页面显示linkText指向ControllerName对应的Controller的actionName方法
public string ActionLink(string linkText, string actionName, string controllerName) {
if (String.IsNullOrEmpty(linkText)) {
throw new ArgumentException(MvcResources.Common_NullOrEmpty, "linkText");
}
if (String.IsNullOrEmpty(actionName)) {
throw new ArgumentException(MvcResources.Common_NullOrEmpty, "actionName");
}
if (String.IsNullOrEmpty(controllerName)) {
throw new ArgumentException(MvcResources.Common_NullOrEmpty, "controllerName");
}
return GenerateLink(linkText, null /* routeName */, actionName, controllerName, new RouteValueDictionary());
}
//
public string ActionLink(string linkText, string actionName, string controllerName, object values) {
if (String.IsNullOrEmpty(linkText)) {
throw new ArgumentException(MvcResources.Common_NullOrEmpty, "linkText");
}
if (String.IsNullOrEmpty(actionName)) {
throw new ArgumentException(MvcResources.Common_NullOrEmpty, "actionName");
}
if (String.IsNullOrEmpty(controllerName)) {
throw new ArgumentException(MvcResources.Common_NullOrEmpty, "controllerName");
}
return GenerateLink(linkText, null /* routeName */, actionName, controllerName, new RouteValueDictionary(values));
}
public string ActionLink(string linkText, string actionName, string controllerName, RouteValueDictionary valuesDictionary) {
if (String.IsNullOrEmpty(linkText)) {
throw new ArgumentException(MvcResources.Common_NullOrEmpty, "linkText");
}
if (String.IsNullOrEmpty(actionName)) {
throw new ArgumentException(MvcResources.Common_NullOrEmpty, "actionName");
}
if (String.IsNullOrEmpty(controllerName)) {
throw new ArgumentException(MvcResources.Common_NullOrEmpty, "controllerName");
}
if (valuesDictionary == null) {
throw new ArgumentNullException("valuesDictionary");
}
return GenerateLink(linkText, null /* routeName */, actionName, controllerName, new RouteValueDictionary(valuesDictionary));
}
使用实例代码
<li>
<%= Html.ActionLink("Home","Index")%>
</li>
<li>
<%= Html.ActionLink("About","About")%>
</li>
<li>
<%=Html.ActionLink("Products","Detail","Products" )%>
</li>
<li>
<%=Html.ActionLink("Products","Detail","Products" ,2)%>
</li>
[教程]ASP.Net MVC定义URL Routing
文/QLeelulu 出处/博客园
定义URL Routing
在一个route中,通过在大括号中放一个占位符来定义( { and } )。当解析URL的时候,符号"/"和"."被作为一个定义符来解析,而定义符之间的值则匹配到占位符中。route定义中不在大括号中的信息则作为常量值。
下面是一些示例URL:
![]()
通 常,我们在Global.asax文件中的Application_Start事件中添加routes,这确保routes在程序启动的时候就可用,而且 也允许在你进行单元测试的时候直接调用该方法。如果你想在单元测试的时候直接调用它,注册该routes的方法必需是静态的同时有一个 RouteCollection参数。
下面的示例是Global.asax中的代码,演示了添加一个包含两个URL参数action 和 categoryName的Route对象:
{
RegisterRoutes(RouteTable.Routes);
}
public static void RegisterRoutes(RouteCollection routes)
{
routes.Add(new Route
(
"Category/{action}/{categoryName}"
, new CategoryRouteHandler()
));
}
设置Route参数的默认值
当你定义个一route的时候,你可以分配一个默认值给route的参数。默认值是当URL中没有包含参数的值的时候使用的。你可以在Route类中通过dictionary来设置Default属性来设置route的默认值:
{
RegisterRoutes(RouteTable.Routes);
}
public static void RegisterRoutes(RouteCollection routes)
{
routes.Add(new Route
(
"Category/{action}/{categoryName}"
new CategoryRouteHandler()
)
{
Defaults = new RouteValueDictionary
{{"categoryName", "food"}, {"action", "show"}}
}
);
}
当URL Routing处理URL Request的时候,上面route定义产生的结果如下表所示:
[教程]使用.Net的CodeDOM技术实现语言无关的Code Wizard
本文曾发表于It168:http://tech.it168.com/m/2007-09-11/200709111500188.shtml
摘要:CodeDOM是.net framework的一项重要的源代码生成技术。本文详细讨论了CodeDOM的原理以及如何利用CodeDOM技术实现一个与语言无关的Code Wizard。并给出了一个用C#语言实现的例子。
关键字:Code Wizards、CodeDOM、.net framework、数据表、模板文件
一、什么是CodeDom?
现在的程序规模越来越 大,虽然在计算发展的几十年间,产生了许多快捷、高效的编程语言和开发工具,如C#、Visual Studio、java等。也产生了许多用以辅助软件设计、开发的思想和方法,如UML、OOP、Agile等。尽管利用这些技术和方法可以大大提高程序 编写的效率,但是仍可能有重复的编码工作。因此,现在出现了许多可以自动产生源代码或者目标文件的软件,即Code Wizards。
一般这些Code Wizards在生成源代码时都是通过设置模板文件,然后根据这些模板文件生成源代码。有很多Code Wizards只能生成固定的语言(如java、C#等)。虽然有一些Code Wizards可 以生成多种语言,但也只是固定的几种。而且生成源代码部分都是显示地固定在程序中。这样非常不易扩展。如CodeSmith系统,这是一个非常不错的 Code Wizard。它使用一个扩展名为cst的文件来设置模板。这个模板文件的格式类似于ASP.NET。如果想生成C#源代码,必须要在其中显示地标明,并 且模板的固定部分要使用C#语言编写。如果这样的话,同样功能要生成不同语言的代码,如C#和VB.net。就要编写两个模板文件。这是非常不方便的。
从以上的描述来看, Code Wizard所 面临的一个重要问题就是如何使用一个模版文件来生成不同语言的源代码。幸好Microsoft提供了一种解决方案,这就是CodeDOM技术。 CodeDOM的全称是代码文档对象模型(Code Document Object Model)。整个CodeDOM就是一张对象图(object graph)。它用这张图中的所有对象描述了面向对象语言中的几乎所有的语法现象,如类、接口、方法、属性等。CodeDOM通过对象模型对语言进行了抽象,然后利用具体语言所提供的生成源代码的机制来生成源代码,并可调用相应的编译器将源码生成*.dll或*.exe。从而可以达到与语言无关的目的。图1描述了使用CodeDOM生成和编译源代码的过程。

图1 CodeDom生成和编译源代码的过程
从上图可以看出,CodeWizard只使用CodeDOM对语言进行抽象,然后通过CodeDomProvider生成源代码。最后通过编译器生成中间语言。下面将详细讨论如何利用CodeDOM来实现CodeWizard。
二、实现CodeWizard
下面要实现的这个 CodeWizard非常简单。其功能主要是将一个数据表映射成一个类。这个类提供了Add和Save方法以及和数据表的每个字段相对应的属性。使用这个 类可以向数据表添加记录。为了便于描述,将这个数据表保存成xml文件格式。每条记录为一个item结点,每一个字段为这个结点的一个属性。表名为这个 xml文件的根结点名称。这个xml文件的格式如下所示:
<item id = "01 " name = "Bill "/>
<item id = "02" name = "Mike" />
</MyTable>
这个CodeWizard通过一个模板文件来定义数据表的结构。模板文件的格式如下:
<id type = "System.Int32"/>
<name type = "System.String"/>
</MyTable>
其中type为字段的类 型,它的值是在.net framework中的System中定义的简单类型,如System.Int32、System.String、System.Char等。下面就详细 讨论如何利用这个模板文件和CodeDOM技术来生成C#和VB.net的源代码。
三、CodeDOM的结构
CodeDOM由两部分组成:
1. 用于描述抽象代码结构的一组类。其中CodeCompileUnit类是这些类的根。代表一个源码文件(如C#的*.cs和VB.net的*.vb)。在使用CodeDOM时,必须先建立一个CodeCompileUnit类的对象,然后在这个对象中加入必要的namespace、class等面向对象元素。
用于生成和编译源代码的类。这个类必须从CodeDomProvider类继承。每种.net framework
所支持的语言都有自己的CodeDomProvider类。如在C#中的CodeDomProvider类叫CSharpCodeProvider,而在VB.net中叫VBCodeProvider。
四、数据表类的定义
要用CodeDOM定义一个类需要三步:
1. 建立一个CodeCompileUnit对象。这个类相当于一个源码文件。
2. 建立一个CodeNamespace对象。理论上在.net framework上运行的程序语言,如C#、VB.net
等,可以没有namespace。但在CodeDOM中必须使用这个类,如果不想要namespace,可以将namespace的名字设为 null或空串。
建立一个CodeTypeDeclaration对象。这个类可以建立Class和Interface两种Type。在
这个例子中只建立Class。如果想建立Interface,只需将IsInterface属性设为true即可。
主要的实现代码如下:
private CodeNamespace m_CodeNameSpace;
private CodeTypeDeclaration m_Class;
private void InitCodeDom()
{
m_CodeCompileUnit = new CodeCompileUnit();
m_CodeNameSpace = new CodeNamespace("xml.tables");
m_CodeCompileUnit.Namespaces.Add(m_CodeNameSpace);
m_Class = new CodeTypeDeclaration(m_ClassName);
m_CodeNameSpace.Types.Add(m_Class);
}
其 中namespace的名子是“xml.tables”。在建立完namespace后,将其加入到m_CodeCompileUnit的 Namespaces集合中。m_ClassName是一个String变量,它的值就是数据表的表名。最后将所建立的类加入到namespace的 Types集合中。在产生完类后。需要在这个类中加入四部分内容,它们分别是:全局变量、属性、构造函数和方法(Add和Save方法)。下面就分别讨论 它们的实现过程。
五、全局变量的生成
这个数据表类中有四种全局变量:用于操作xml文件的类型为XmlDocument的变量、用于保存数据表文件名的变量、用于确定是否为加入状态的Boolean型变量、以及用于保存每个字段值的变量组。具体实现代码如下:
{
// 产生 "private XmlDocument m_xml = new XmlDocument();"
CodeMemberField xml = new CodeMemberField("System.Xml.XmlDocument", "m_xml");
CodeObjectCreateExpression createxml = new CodeObjectCreateExpression("System.Xml.XmlDocument");
xml.InitExpression = createxml;
m_Class.Members.Add(xml);
// 产生 "private String m_XmlFile;"
CodeMemberField xmlfile = new CodeMemberField("System.String", "m_XmlFile");
m_Class.Members.Add(xmlfile);
// 根据模板文件产生保存字段值的变量
String fieldname = "", fieldtype = "";
foreach (XmlNode xn in m_Xml.DocumentElement.ChildNodes)
{
fieldname = "m_" + xn.Name;
fieldtype = xn.Attributes["type"].Value;
CodeMemberField field = new CodeMemberField(fieldtype, fieldname);
m_Class.Members.Add(field);
}
// 产生 "private bool m_AddFlag;"
CodeMemberField addflag = new CodeMemberField("System.Boolean", "m_AddFlag");
m_Class.Members.Add(addflag);
}
在以上代码中每段程序上方的注释是它们所生成的C#源代码。在输入这段代码之前,需要引入两个namespace。
using System.CodeDom.Compiler;
五、属性的生成
在数据表类中每个属性代表数据表的一个字段,名子就是字段名。这些属性和保存字段的全局变量一一对应。下面是具体的实现代码:
{
String fieldname = "", fieldtype = "";
foreach (XmlNode xn in m_Xml.DocumentElement.ChildNodes)
{
fieldname = xn.Name;
fieldtype = xn.Attributes["type"].Value;
CodeMemberProperty property = new CodeMemberProperty();
property.Attributes = MemberAttributes.Public | MemberAttributes.Final;
property.Name = fieldname;
property.Type = new CodeTypeReference(fieldtype);
property.HasGet = true;
property.HasSet = true;
CodeVariableReferenceExpression field = new CodeVariableReferenceExpression("m_" + fieldname);
// 产生 return m_property
CodeMethodReturnStatement propertyReturn = new CodeMethodReturnStatement(field);
property.GetStatements.Add(propertyReturn);
// 产生 m_property = value;
CodeAssignStatement propertyAssignment = new CodeAssignStatement(field,
new CodePropertySetValueReferenceExpression());
property.SetStatements.Add(propertyAssignment);
m_Class.Members.Add(property);
}
}
这些生成的属性是可读写的。这就需要将HasGet和HasSet两个属性设为true,然后分别将get和set方法中的语句分别加到GetStatements和SetStatements中。
六、构造函数的生成
构造函数的主要工作是打开数据表。如果数据表不存在,就创建这个数据表文件。在编写代码之前,需要先定义三个全局变量。因为这三个全局变量在程序中会多次用到。它们的类型都是CodeVariableReferenceExpression。这个类型变量其实在生成源码中的作用就是对某一个变量的引用。具体的实现代码如下:
private CodeVariableReferenceExpression m_XmlExpression;
private CodeVariableReferenceExpression m_AddFlagExpression;
private void InitVariants()
{
m_XmlFileExpression = new CodeVariableReferenceExpression("m_XmlFile");
m_XmlExpression = new CodeVariableReferenceExpression("m_xml");
m_AddFlagExpression = new CodeVariableReferenceExpression("m_AddFlag");
}
下面是生成构造函数的源代码:
{
// 定义构造函数
CodeConstructor constructor = new CodeConstructor();
constructor.Parameters.Add(new CodeParameterDeclarationExpression("System.String", "xmlFile"));
constructor.Attributes = MemberAttributes.Public;
// 产生 "m_XmlFile = xmlFile;"
CodeAssignStatement assignXmlFile = new CodeAssignStatement(m_XmlFileExpression,
new CodeVariableReferenceExpression("xmlFile"));
// 产生 "m_xml.LoadXml("…");"
CodeMethodInvokeExpression invokeLoadXml = new CodeMethodInvokeExpression(m_XmlExpression, "LoadXml",
new CodePrimitiveExpression("<?xml version=\"1.0\" encoding=\"gb2312\" ?><" + m_Xml.DocumentElement.Name
+ "></" + m_Xml.DocumentElement.Name + ">"));
// 产生 "m_xml.Save(m_XmlFile);"
CodeMethodInvokeExpression invokeSave = new CodeMethodInvokeExpression(m_XmlExpression, "Save",
m_XmlFileExpression);
CodeStatementCollection statements = new CodeStatementCollection();
statements.Add(invokeLoadXml);
statements.Add(invokeSave);
// 产生if语句: "if (System.IO.File.Exists(m_XmlFile))
else
"CodeConditionStatement ifStatement = new CodeConditionStatement(new CodeMethodInvokeExpression(
new CodeVariableReferenceExpression("System.IO.File"), "Exists", m_XmlFileExpression), new CodeStatement[] { } ,
new CodeStatement[] { statements[0], statements[1] });
// 产生 "m_xml.Load(m_XmlFile);"
CodeMethodInvokeExpression invokeLoad = new CodeMethodInvokeExpression(m_XmlExpression, "Load",
m_XmlFileExpression);
// 产生 "m_AddFlag = false;"
CodeAssignStatement assignAddFalse = new CodeAssignStatement(m_AddFlagExpression,
new CodePrimitiveExpression(false));
constructor.Statements.Add(assignXmlFile);
constructor.Statements.Add(ifStatement);
constructor.Statements.Add(invokeLoad);
constructor.Statements.Add(assignAddFalse);
m_Class.Members.Add(constructor);
}
七、Add和Save方法生成
Add方法只有一条语句,功能是将m_AddFlag设为true,以使数据表类处于加入状态。Save方法比较复杂。它的功能是当m_AddFlag为true时在数据表文件的最后加入一条记录,并保存。具体实现代码如下:
{
CodeTypeReference voidReference = new CodeTypeReference("System.void");
//产生Add方法
CodeMemberMethod add = new CodeMemberMethod();
add.ReturnType = voidReference;
add.Name = "add";
add.Attributes = MemberAttributes.Public | MemberAttributes.Final;
CodeAssignStatement assignAddTrue = new CodeAssignStatement(m_AddFlagExpression,
new CodePrimitiveExpression(true));
add.Statements.Add(assignAddTrue);
m_Class.Members.Add(add);
//产生Save方法
CodeMemberMethod save = new CodeMemberMethod();
save.ReturnType = voidReference;
save.Name = "save";
save.Attributes = MemberAttributes.Public | MemberAttributes.Final;
System.Collections.Generic.List<CodeStatement> ifStatements =
new System.Collections.Generic.List<CodeStatement>();
//产生 "XmlNode xn = m_xml.CreateNode(XmlNodeType.Element, "item", "");"
CodeVariableDeclarationStatement xmlNode = new CodeVariableDeclarationStatement("System.Xml.XmlNode", "xn");
CodeMethodInvokeExpression createNode = new CodeMethodInvokeExpression(m_XmlExpression, "CreateNode",
new CodeExpression[] {new CodeVariableReferenceExpression("System.Xml.XmlNodeType.Element"),
new CodePrimitiveExpression("item"),
new CodePrimitiveExpression("") });
xmlNode.InitExpression = createNode;
ifStatements.Add(xmlNode);
//产生 "XmlAttribute xa = null; "
CodeVariableDeclarationStatement xmlAttr = new CodeVariableDeclarationStatement("System.Xml.XmlAttribute", "xa");
xmlAttr.InitExpression = new CodePrimitiveExpression(null);
ifStatements.Add(xmlAttr);
//产生字段属性
CodeStatementCollection statements = new CodeStatementCollection();
foreach (XmlNode xn in m_Xml.DocumentElement.ChildNodes)
{
CodeMethodInvokeExpression createAttribute = new CodeMethodInvokeExpression(m_XmlExpression,
"CreateAttribute", new CodePrimitiveExpression(xn.Name));
CodeAssignStatement assignxa = new CodeAssignStatement(
new CodeVariableReferenceExpression("xa"), createAttribute);
CodeMethodInvokeExpression invokeToString = new CodeMethodInvokeExpression(
new CodeVariableReferenceExpression("m_" + xn.Name), "ToString");
CodeAssignStatement assignValue = new CodeAssignStatement(
new CodeVariableReferenceExpression("xa.Value"), invokeToString);
CodeMethodInvokeExpression invokeAppend = new CodeMethodInvokeExpression(
new CodeVariableReferenceExpression("xn.Attributes"),
"Append", new CodeVariableReferenceExpression("xa"));
statements.Add(invokeAppend);
ifStatements.Add(assignxa);
ifStatements.Add(assignValue);
ifStatements.Add(statements[0]);
}
// 产生 "m_xml.DocumentElement.AppendChild(xn);"
CodeMethodInvokeExpression invokeAppendChild = new CodeMethodInvokeExpression(new
CodeVariableReferenceExpression("m_xml.DocumentElement"), "AppendChild",
new CodeVariableReferenceExpression("xn"));
statements.Clear();
statements.Add(invokeAppendChild);
ifStatements.Add(statements[0]);
// 产生 "m_xml.Save(m_XmlFile);"
CodeMethodInvokeExpression invokeSave = new CodeMethodInvokeExpression(m_XmlExpression,
"Save", m_XmlFileExpression);
statements.Clear();
statements.Add(invokeSave);
ifStatements.Add(statements[0]);
// 产生 "m_AddFlag = false;"
CodeAssignStatement assignAddFalse = new CodeAssignStatement(m_AddFlagExpression,
new CodePrimitiveExpression(false));
ifStatements.Add(assignAddFalse);
// 产生if语句: "if (m_AddFlag)"
CodeConditionStatement ifStatement = new CodeConditionStatement(m_AddFlagExpression,
ifStatements.ToArray());
save.Statements.Add(ifStatement);
m_Class.Members.Add(save);
}
八、生成源代码
生成具体语言的源代码需要一个从CodeDomProvider继承的类。对于C#而言是CSharpCodeProvider类。实现代码如下:
public void SaveCSharp(String filename)
{
IndentedTextWriter tw = new IndentedTextWriter(new StreamWriter(filename, false), " ");
CodeDomProvider provide = new CSharpCodeProvider();
provide.GenerateCodeFromCompileUnit(m_CodeCompileUnit, tw, new CodeGeneratorOptions());
tw.Close();
}
在使用CSharpCodeProvider类时需要用到m_CodeCompileUnit这个全局变量。这样可产生一个*.cs文件。以上代码中的IndentedTextWriter类是建立一个文件的Writer,用于向这个文件中输出源代码。但和其它的Writer不同的是它的输出是缩进的(以四个空格进行缩进)。如是想生成VB.net的代码,只需将CSharpCodeProvider改为VBCodeProvider即可。
九、编译源代码
到 现在为止,这个数据表类的源代码已经全部生成了。你可以将这个源文件直接加入到自己的工程中。或者直接将其编译成*.dll文件,然后在程序中调用。如果 想编译,可以直接调用指定语言的编译器(如C#中的csc.exe)。但这样不是太方便。在CodeDOM中提供了一种机制,可以在程序中通过 CodeDomProvider直接调用指定语言的编译器。下面是编译C#源程序的一个例子。
{
CompilerParameters cp = new CompilerParameters(new String[] { "System.Xml.dll" }, targetFile, false);
CodeDomProvider provider = new CSharpCodeProvider();
cp.GenerateExecutable = false;
// 调用编译器
CompilerResults cr = provider.CompileAssemblyFromFile(cp, sourcefile);
if (cr.Errors.Count > 0)
{
// 显示编译错误
foreach (CompilerError ce in cr.Errors)
System.Windows.Forms.MessageBox.Show(ce.ToString());
}
}
对于以上代码有两点说明:
- 使用CodeDomProvider调用编译器时也需要传递相应的参数,如在本例中将System.Xml.dll
作为一个参数,表示目标文件需要调用这个dll中的资源。
- 在调用编译器后,如果出现错误,可使用cr.Errors获得错误信息。
十、结束语
我花了一个晚上的时间实现了这个简单的例子,并用C#2.0调试通过,只是为了抛砖引玉。自动生成源代码有很多的方法,但使用CodeDom生成源代码会有更大的灵活性,主要表现在以下三个方面:
1. 语言无关。即只要是.net framework所支持的语言,并且这种语言提供了CodeDomProvider。
就可以生成这种语言的源代码。
2. 如果所生成的语言是测试版或要将这种语言升级到下一个版本,也可以考虑使用CodeDOM。
因为当这种语言的语法有所变化时,CodeDomProvider也会随之升级。因此,使用CodeDOM的Code Wizards也会随着CodeDOM而升级,这样就不必修改Code Wizards的源代码了。
3. 如果所生成的一种语言是你所不熟悉的,如果不使用CodeDOM,必须要熟悉这种语言的语
法,才能生成它的源代码。而使用CodeDOM却可以避免这一点。因为CodeDOM是使用抽象的object graph来描述语言的。而语言的具体语法是由CodeDomProvider所决定的。
其实CodeDOM不仅可以用在Code Wizards上,也可以用在许多其它地方,如可以生成Web
Services的客户端代理(Client Proxies),或根据UML图生成类的构架代码。总之,使用CodeDom可以大大降低和语言的偶合度,并且很容易维护和升级系统。
[资源]国外几款开源的CMS
1、Ludico
Ludico是C#编写的居于ASP.NET 2.0的Portal/CMS系统。它的模块化设计是你可以按照你希望的使用或开发网站功能。它里面有高级的用户管理,一个所见即所的(WYSIWYG)的编辑器等。
下载地址:http://sourceforge.net/projects/ludico/
2、umbraco
Umbraco是一款在.net平台下C#开发的开源内容管理系统,该系统效率,灵活,用户界面都不错。
下载地址:http://umbraco.org/
3、mojoPortal
mojoPortal是一款C#开发的面相对象网站框架,它可以运行于Windows的ASP.NET 和GNU/Linux 或Mac OS X的Mono的平台上。
下载地址:http://www.mojoportal.com/
4、Kodai CMS
Kodai CMS是.net平台下的一款功能齐全的内容管理系统。
下载地址:http://www.gotdotnet.com/workspaces/workspace.aspx?id=070f30c3-6089-4a75-b84c-fac654a7ec08
5、nkCMS
NkCMS是使用ASP.net和SQL server 2000开发的内容管理系统。
下载地址:http://nkcms.sourceforge.net/
6、Go.Kryo
Go.Kryo是一个用ASP.net(C#).NET 实现的简单的内容管理系统,后台数据库使用Microsoft SQL Server 。
下载地址:http://sourceforge.net/projects/gokryo/
7、Amplefile
Amplefile是一款内容管理系统,是.net环境下的windows应用程序,使用了.Net remoting.
下载地址:http://sourceforge.net/projects/amplefile/
8、ndCMS
ndCMS是 ASP.net (C#)下的一个内容管理系统。它提供了用户管理,文件管理,一个WYSIWYG编辑器,模板管理,拼写检查和内置的http压缩。ndCMS的目标是提供一个简单而快速的方式部署.Net站点
下载地址:http://ndcms-net.sourceforge.net/
9、Cuyahoga
Cuyahoga是C#开发的灵活的CMS / Portal 解决方案。它可以运行于Microsoft .net 和Mono 平台,支持SQL Server, PostgreSQL或MySQL作为底层数据库。
下载地址:http://www.cuyahoga-project.org/
10、Rainbow
Rainbow项目是一款使用Microsoft's ASP.net和C#技术开发的有丰富功能的开源内容管理系统。
下载地址:http://www.rainbowportal.net/Rainbow/Default.aspx
[资源].net的项目汇总
经过微软.net Framework 2.0的革新,.net平台的开发越来越精彩。笔者收集基于.net开发的n个项目,一方面为新手提供有价值学习资源,培养起软件开发的乐趣,另一方面共勉已从事.net领域工作多年并有明确发展目标的同仁,提高自己,更上一层楼。
SharpDevelop
强大的插件系统,通过Addin构建成一个功能齐全的.net开发IDE。核心是AddInTree。跟随这个项目开发许多有用的组件,比如功能文本编辑器(ICSharpCode.TextEditor),SharpZipLib等。
链接:http://www.icsharpcode.net/
DotNetNuke
这个就是著名DNN,使用VB.NET进行开发。通过其基本架构可进行堆积木式快速建站。而且支持子网站系统。其由ASP.NET Portal start kit进化而来。
链接:http://www.dnnchina.net/ ,http://www.dotnetnuke.com
Community Server
这个也是一个很著名的ASP.NET项目,记得好像最早系统原形为ASP.NET Forums,后来加入了.Text Blog 和nGallery成为一个完整的通用系统。对应的中文版本为宝玉修改的CCS。
链接:http://communityserver.org/
Rainbow
另外一个类似于DNN的系统,使用C#进行开发。
链接:http://www.rainbowportal.net/
RssBandit
一个客户端的RSS查看器,使用C# 进行开发,最大的特点是数据存储采用xml文件。
链接:http://www.rssbandit.org/
FreeTextbox
Web上的一个Html超文本编辑器,早些版本是开源的,现在还是免费使用,不过源代码需要购买。
链接:http://www.freetextbox.com
World Wind
使用.NET开发的一个Windows窗体系统,以地球外观看得角度提供全球定位功能,类似于Google Earth。
链接:http://worldwind.arc.nasa.gov
log4net
对应Java中的log4j。一个强大的日志管理模块。
链接:http://logging.apache.org/log4net/
Monodevelop
非Windows 系统下的.net 平台开发工具。
链接:http://www.monodevelop.com
Paint.NET
使用.net开发的画图软件,功能不错。
链接:http://www.getpaint.net/index.html
Nunit
对应Java中的Junit,非常著名的单元测试工具。
链接:http://www.nunit.org/
FCKeditor
Web上的又一个Html超文本编辑器。
链接:http://www.fckeditor.net/
Nlog
一个日志管理库,类似于Log4Net。
链接:http://www.nlog-project.org/
ManagedSpy
.net 平台下的Spy ++,支持通过.net 2.0开的Windows Forms应用程序。
链接:http://msdn.microsoft.com/msdnmag/issues/06/04/ManagedSpy/
Guidance Explore
类似于一个.net平台编程问题简答的FAQ。不过提供的都是英文。
链接:http://www.codeplex.com/Wiki/View.aspx?ProjectName=guidanceExplorer
Terrarium
一个.net开发的多人游戏。玩这个游戏可以提高编程能力^_^。
链接:http://www.windowsforms.net/Default.aspx?tabindex=4&tabid=49
TaskVision
任务管理系统,一个经典的Smart Client智能客户端程序。
链接:http://www.windowsforms.net/Default.aspx?tabindex=4&tabid=49
IssueVision
事务管理系统,Smart Client智能客户端程序。
链接:http://www.windowsforms.net/Default.aspx?tabindex=4&tabid=49
FotoVision
又一个值得学习的.net开发的Windows应用程序。
链接:http://www.windowsforms.net/Default.aspx?tabindex=4&tabid=49
Infragistics Tracker Application
由Infragistics开发的Smart Client智能客户端程序。
链接:http://www.windowsforms.net/Default.aspx?tabindex=4&tabid=49
Windows Forms RSS Portal
一个.net 开发的聚合器。
链接:http://www.windowsforms.net/Default.aspx?tabindex=4&tabid=49
Enterprise Library
微软的企业库,对原早些时候开发的一些Block 模块进行整合提供企业统一的接口,新版本使用了.net 2.0的的许多功能。
链接:http://msdn.microsoft.com/practices/
PetShop
基于N-tier设计的电子商务网站,没什么好说的了。
链接:http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnbda/html/bdasamppet4.asp
XmlNotepad
一个用.net 开发的xml文件编辑器。
链接:http://www.microsoft.com/china/msdn/library/data/xml/xmlnotepad.mspx
DockManager Control
一个很不错的实现类似于VS 2005的界面某些功能的组件。
链接:http://www.codeproject.com/vb/net/DockPanelSkin.asp
Starter Kits for Visual Web Developer
该套件为学习研究应用asp.net2.0的开发人员提供许多宝贵资源,很不错。
链接:http://www.asp.net/downloads/starterkits/default.aspx?tabid=62
以上是笔者的一些资源积累,还有需多经典项目案例没有包括,比如一些早期微软提供的项目案例以及现在热门的ORM经典框架。
[教程]ASP.net学习路线
如果你已经有较多的面向对象开发经验,跳过以下这两步:
第一步 掌握一门.NET面向对象语言,C#或VB.NET 我强烈反对在没系统学过一门面向对象(OO)语言的前提下去学ASP.NET。 ASP.NET是一个全面向对象的技术,不懂OO,那绝对学不下去!
第二步 对.NET Framework类库有一定的了解 可以通过开发Windows Form应用程序来学习.NET Framework。ASP.NET是建构在.NET Framework之上的技术,你对.NET Framework了解得越深,学习ASP.NET就越快。 举个例子:下面简单列出几个对掌握ASP.NET非常重要的概念:对象的内存模型,委托,事件,多线程,程序集和应用程序域,安全模型 .NET Framework当然还有许多其它的东西,但不理解与把握清楚上述这些东西,是很难真正把握ASP.NET的。出于急迫的心情与现实的考虑,不少人没有扎实的面向对象基础就想直接学习ASP.NET,其结果只能是欲速则不达。在具备了OO基础之后,以下是具体的学习ASP.NET技术步骤。
第一步:学习HTML与CSS
这并不需要去学一大堆的诸如Dreamweaver,Firework之类的各种网页设计工具,关键是理解HTML网页嵌套的block结构与CSS的box模型。许多 ASP.NET控件最后都必须转化为HTML。而且,div+CSS是当前主流的网页布局模型。学习这部分时,关键在于理解概念,而不需要将精力花在美化页面的许多技巧上,那是网站美工的工作,不是程序员的工作。
第二步:学习JavaScript
JavaScript不是Java,它主要运行于浏览器端。可以完成许多工作,功能也很强大:比如它将客户端网页中的HTML元素看成一棵树,可以编写代码访问并修改树节点,动态生成新的HTML代码,从而达到动态修改网页显示特性的目的。
JavaScript在目前的网站开发中用得很多,非常重要。
另外,它也是目前非常流行的AJAX技术的基础。
第三步:学习计算机网络原理
找一本大学<计算机网络>教材,重点看看它的有关互联网的部分,了解一些域名解析和HTTP协议等知识。这是进行互联网开发的理论基础。
第四步:学习ASP.NET表示层技术,会设计Web页面
需要结合先前打好的面向对象技术的基础,至少掌握以下内容:
(1) 各种Web控件的使用方法,
(2) 理解信息在网页中的传送方式,比如Cookie,ViewState,Session等的使用。
(3) ASP.NET应用程序与网页的生命周期,以及相关对象(比如httpcontext,response,request)的用途。
(4) ASP.NET实现事件驱动的内幕
(5) 自定义用户控件
再次强调一下,没有OO基础,很难掌握上述技术,就只能被这些东东牵着鼻子走了,会很被动。
第五步 掌握数据库技术
具体地说,要学习以下内容:
(1) 学会使用SQL Server 2005:不要求精通它的各种工具与管理配置技术,但至少知道如何连接,如何建表,如何创建存储过程
(2) 学习ADO.NET,掌握使用代码人工访问数据库(别用VS2005的向导)的方法
(3) 学习数据绑定控件的使用
第六步 理解多层架构
这时,先前在OO学习阶段涉及到的程序集与应用程序域等就派上用场了,现在,网站架构大多采用多层架构:表示层、业务逻辑层、数据存取层以及数据库本身。
可以先上网找一此多层架构的资料看,再找一个现成的比较复杂的开源ASP.NET项目分析一下其架构就差不多了。基本上都是一个套路,到处应用。
有的朋友问:学习架构是不是必须学习设计模式。
我的看法是:不必!当然,你如果学习过设计模式,那当然更好。但在实际开发中,如果只想着机械地套用某种模式,反而起不到好的结果。我的观点:在学习设计模式时要多思多悟,其思想就会渐渐地融入你的大脑,在真实的设计实践中,忘掉所有的写在书上的模式,一切从实际出发,相信你的直觉,只要达到设计要求的方案就是可行的方案,事实上,你这样做了之后,回过头来再看,会发现你的设计往往暗合设计模式的理论。
第七步 学习XML与Web Service
先了解XML的基础知识,找本讲XML的书看一下就差不多了,然后,再学习Web Service。Web Service其实可类比为远程方法调用(以XML格式表达的调用信息)。
学 到了这里,如果你还有兴趣,不妨再去看看SOA,不过SOA的资料都是理论与概念,看起来比较郁闷,而且离实际开发可能比较远。所以,这是可选项。
第八步 学习AJAX
学习AJAX的主要目的是创建具有更丰富特性的Web表示层,而经过前面七步的学习,到此再学习AJAX已水到渠成,所有的基础都已具备,不会有太大的问题了。
在基础未具备的前提下直接学AJAX,就象“浮沙之上筑高台”,所以,将AJAX的学习次序安排在这里。
第九步 学习RIA技术
RIA:Rich internet application,可看成是将C/S与B/S优点合二为一的尝试。就具体技术来说,主要指微软的Silverlight(WPF_E),毕竟前头一路行来都是微软路线。
不过目前学习它主要是为了技术储备。估计此技术的普及需要2到3年的时间,因为预装Vista的机器今年才开始大卖。
本贴来自ZDNetChina中文社区 http://bbs.zdnet.com.cn ,本贴地址:http://bbs.zdnet.com.cn/viewthread.php?tid=108315
[教程]解读ASP.NET TimeTracker Starter Kit(2)——重构篇
看了ASP.NET Time Tracker Starter Kit的代码以后,觉得这个程序是学习面向对象编程开发的一个好案例。整个程序从功能上来讲就是记录人员参加项目工作的工时记录。分析得出主要有人员、项目、工时记录这几个类。整个程序正好是以这几个类为基础展开的。在业务逻辑层里TTUser(用户类)、Project(项目类)和TimeEntry(工时记录类)分别就包括了对相应表的增、删、改等操作和整个程序中所用到的对这几个主要对象的各种操作。整个程序在类的划分和功能上做的很好,但是我觉得在三层架构的划分上不是很理想。
业务逻辑层包含的许多数据访问层的东西,如:数据库连接信息、用到的存储过程等。而这些信息我觉得放在数据访问层应该会更好一些。作为数据访问层,应该为数据逻辑层提供访问数据库的方法,而不是只提供一个简化数据访问的组件(DAAB)。假设要使用Oracle数据,那么改动的代码就需要改动很多,同时也不利于将来的改动。
我的想法是:彻底的将与数据相关的操作从数据逻辑层分离出去,对数据访问层只提供访问方法。在数据访问层的设计上,还是沿用“为数据访问层编写一个基类”的方法,通过基类访问DAAB。这样一来如果要变换为Oracle数据库,只要修改DAAB中的内容即可。大家帮忙看看我的改进代码,看看思路有无问题。
数据访问层基类:
数据访问层代码:(以项目类数据访问层代码为例)
业务逻辑层代码:(以项目类业务逻辑层代码为例)
更多相关内容:点击这里>>
Mikel
