2005年01月18日

功能非常强大,除了支持常见的功能(字体、字号、颜色等),还支持表格、Form等。FCKeditor的官方网站在这里。在官方网站上还有一个在线的演示。FCKeditor对IE、Mozilla Firefox中的支持很好。刚才写blog的时候发现原来donews.net的HTML编辑器就是FCKeditor,不过FCKeditor可以很好的支持多语言的,怎么donews.net使用的还是英文的,怎不用中文的。

下面时首页上的特性说明:

Features
  • Internet Explorer 5.5+ and Gecko browser (Mozilla / Firefox / Netscape) compatibility
  • XHTML 1.0 support
  • Font formatting: type, size, color, style, bold, italic, etc
  • Text formatting: alignment, indentation, bullets list, etc
  • Cut, Paste and Past as Plain Text, Undo and Redo
  • Paste from Word cleanup with auto detection
  • Link creation
  • Anchors support (version 1.x)
  • Image insertion, with upload and server browsing support
  • Table creation and editing (add, delete rows, etc)
  • Table cells editing (size, colors, etc)
  • Form fields (version 1.x)
  • Right click context menus support
  • Complete toolbar customization
  • Skins support.
  • Spell checker (version 1.x)
  • CSS support for a better integration in your web site
  • Multi-language support with automatic user language detection. Including Right to Left scripting.
  • Lightweight and fast
  • Automatic browser detection and customization
  • Integration with ASP, ASP.NET, Java, ColdFusion, PHP, Javascript and IE Behaviours (version 1.x)
  • Image and file links upload and server repository browser.
  • For web developer it is easy to install and customize
  • For web users it’s simply easy to use!
2005年01月17日
DataGrid中的数据统计行包含列数据的和、平均值或者其他类型的统计信息,它是具有较多数据的DataGrid中相对独立的一行数据。我用三种方法实现过数据统计行的功能,发现它们各自有自己的优点(当然,也有各自的缺点)。在本文中,对三种实现方法,我都将给出具体的举例,然后,分析讨论在特定的情况下,每一种方法相对其他方法的优点和缺点。为了便于区别,在本文中,我姑且将这三种数据统计行的实现方法称为:RollUp、DataTable Loop和ItemDataBound。现在,我们就分别来看这三种实现方法。
一、RollUp实现方法(实例 | ASPX 代码 | CS 代码 | SQL)
我们知道,RollUp是SQL语句中,使用Group By对数据进行分组时使用的一个参数。在SQL Server在线文档中,这样说明RollUp参数,“它是Group By提供的对常规数据列的一种补充,用于对数据进行汇总、统计,常被称为数据结果集。”使用RoolUp方法的最大好处就是,使用该参数以后,我们从数据库得到的的数据,看上去已经和我们需要显示在页面的差不多了。这样,我们对于数据的处理就会相对较少,我们的代码也会更加简洁、速度更快、更简单。
使用RollUp大另外一个好处是,它返回的结果不止包括一个数据统计行。在这个实例中,我们可以看到,DataGrid中不但对单个年度数据进行了平均值统计,而且,对2000年到2002年的整体平均值数据也进行了统计。而在CS 代码中,代码是很少的:只是简单的在ItemDataBound中改进了数据的显示方式,而对于数据的实质处理语句是没有的。这些功能的实现完全可以使用其他的方法,但是,使用RollUp的方法处理,相当的方便、有效。
在书《Building Web Solutions with ASP.NET and ADO.NET》中,作者Dino Esposito于该书的第六章部分”Chapter 6: Advanced Data Reporting“也提供了一个使用RollUp实现数据统计行的实例。
二、DataTable Loop(实例 | ASPX 代码 | CS 代码
DataTable Loop的实现方法就是在一个DataTable数据表中,通过对DataRows进行循环运算而得到数据统计行数据,循环结束以后,一个包含统计数据的行将加入DataTable中,这样,就将DataTable数据表的最后一行数据作为统计数据行。和RollUp方法相比较,使用这种方法的好处在于,RollUp方法只能针对特定的数据库软件,比如Sql Server 6.5(或者以上)和Oracle 8i(或者以上)等可以实现它的数据统计功能。如果你要从XML取得数据,使用RollUp就无能为力了,而对于DataTable Loop方法而言,显然没有这些限制。
和下面将要介绍的ItemDataBound方法相比,DataTable Loop的另外一个优点是使用该方法的时候,可以在DataGrid的数据绑定之前取得统计数据。当你需要将统计数据显示在页面最上方的时候,这种方法是非常有用的。另外,和ItemDataBound方法不同,DataTable Loop不需要使用一个专门的全局变量。
三、ItemDataBound (实例 | ASPX 代码 | CS 代码)
这种方法似乎在DataGrid的数据统计中比较通用,Dotnetjunkies guru Doug Seven在他的教程Adding a Totals Field in a DataGrid中就使用了这种方法;微软业在其知识库中介绍了这种技术:HOW TO: Create a Summary Row for a DataGrid in ASP.NET by Using Visual Basic .NET
相对于其他两种方法,使用ItemDataBound的优点在于它使用了DataGrid的数据排序功能。因为在数据绑定之前统计数据不存在,因此,数据排序也就相对简单。和其他两种方法不同,使用这种方法实现数据排序不需要任何特殊的处理。和DataTable Loop一样,ItemDataBound也可以适用于任何数据源。
四、实现数据统计列的一个类(CS 代码
为了尽量减少代码重用,我使用了一个用于获取数据统计信息类,该类包含计算“数据和”和“数据平均值”的方法。稍微做一些修改,该类就扩展其他统计信息,比如:“取最小”“取最大”等。
下面是针对以上三种方法的简单比较表:
方法
优点
缺点
ROLLUP
快,简单,代码很少,多次统计
不能用于XML等数据源,如果需要对数据进行排序,会比较麻烦。
DataTable Loop
可以使用XML数据源,在DataGrid数据绑定前生成统计数据。
多次统计比较麻烦,对数据表进行额外循环操作。
ItemDataBound
可以使用XML数据源,数据排序简单。
需要全局变量。
表一
ROLLUP
DataTable Loop
ItemDataBound
性能
X
 
 
排序
 
 
X
多次统计
X
 
 
运行时统计
 
X
X
数据绑定前统计
X
X
 
简单性
X
 
 
任意数据源
 
X
X
表二
2005年01月15日
1. 避免将多个类放在一个文件里面。
2.  一个文件应该只有一个命名空间,避免将多个命名空间放在同一个文件里面。
3.  一个文件最好不要超过500行的代码(不包括机器产生的代码)。
4.  一个方法的代码长度最好不要超过25行。
5.  避免方法中有超过5个参数的情况。使用结构来传递多个参数。
6.  每行代码不要超过80个字符。
7.  不要手工的修改机器产生的代码。
a)  如果需要编辑机器产生的代码,编辑格式和风格要符合该编码标准。
b)  Use partial classes whenever possible to factor out the maintained portions.
8.  避免利用注释解释显而易见的代码。
a)  代码应该可以自解释。好的代码由可读的变量和方法命名因此不需要注释。
9.  Document only operational assumptions, algorithm insights and so on.  
10.  避免使用方法级的文档。
a)  使用扩展的API文档说明之。
b)  只有在该方法需要被其他的开发者使用的时候才使用方法级的注释。(在C#中就是///
11.  不要硬编码数字的值,总是使用构造函数设定其值。
12.  只有是自然结构才能直接使用const,比如一个星期的天数。
13.  避免在只读的变量上使用const。如果想实现只读,可以直接使用readonly。
public class MyClass
{
   public readonly int Number;


   public MyClass(int  someValue) 
   {
      Number = someValue;
   }
   public  const int  DaysInWeek = 7;
}
14.  每个假设必须使用Assert检查
a)  平均每15行要有一次检查(Assert)
using System.Diagnostics;
object GetObject()
{…}
object obj = GetObject();
Debug.Assert(obj != null);
15.  代码的每一行都应该通过白盒方式的测试。
16.  只抛出已经显示处理的异常。
17.  在捕获(catch)语句的抛出异常子句中(throw),总是抛出原始异常维护原始错误的堆栈分配。
catch(Exception exception)
{   
   MessageBox.Show(exception.Message);
   throw ;  //和throw exception一样。
}
18.  避免方法的返回值是错误代码。
19.  尽量避免定义自定义异常类。
20.  当需要定义自定义的异常时:
a)  自定义异常要继承于ApplicationException。
b)  提供自定义的序列化功能。
21.  避免在单个程序集里使用多个Main方法。
22.  只对外公布必要的操作,其他的则为internal。
23.  Avoid friend assemblies, as it increases inter-assembly coupling.
24.  Avoid code that relies on an assembly running from a particular location.
25.  使应用程序集尽量为最小化代码(EXE客户程序)。使用类库来替换包含的商务逻辑。
26.  避免给枚举变量提供显式的值。
//正确方法 
public enum Color
{   
   Red,Green,Blue
}
//避免
public enum Color
{   
   Red = 1,Green =  2,Blue = 3
}
27.  避免指定特殊类型的枚举变量。
//避免 
public enum Color  : long
{   
   Red,Green,Blue
}
28.  即使if语句只有一句,也要将if语句的内容用大括号扩起来。
29.  避免使用trinary条件操作符。
30.  避免在条件语句中调用返回bool值的函数。可以使用局部变量并检查这些局部变量。
bool IsEverythingOK()
{…}
//避免
if (IsEverythingOK ())
{…}
//替换方案 
bool ok = IsEverythingOK();
if (ok)
{…}
31.  总是使用基于0开始的数组。
32.  在循环中总是显式的初始化引用类型的数组。
public class MyClass
{}
MyClass[] array = new  MyClass[100];
for(int index = 0; index < array.Length;  index++)
{
   array[index] = new  MyClass();
}
33.  不要提供public 和 protected的成员变量,使用属性代替他们。
34.  避免在继承中使用new而使用override替换。
35.  在不是sealed的类中总是将public 和 protected的方法标记成virtual的。
36.  除非使用interop(COM+ 或其他的dll)代码否则不要使用不安全的代码(unsafe code)。
37.  避免显示的转换,使用as操作符进行兼容类型的转换。
Dog dog = new GermanShepherd();
GermanShepherd shepherd = dog  as  GermanShepherd;
if (shepherd != null )
{…}
38.  当类成员包括委托的时候
a)  Copy a delegate to a local variable before publishing to avoid concurrency race condition. 
b)  在调用委托之前一定要检查它是否为null
public class MySource
{
   public event EventHandler  MyEvent;
   public void FireEvent()
   {
      EventHandler temp = MyEvent;
      if(temp != null )
      {
         temp(this,EventArgs.Empty);
      }
   }
}  
39.  不要提供公共的事件成员变量,使用事件访问器替换这些变量。
public class MySource
{
   MyDelegate m_SomeEvent ;
   public event MyDelegate SomeEvent
   {
      add
      {
         m_SomeEvent += value;
      }
      remove
      {
         m_SomeEvent -= value;
      }
   }
}
40.  使用一个事件帮助类来公布事件的定义。
41.  总是使用接口。
42.  类和接口中的方法和属性至少为2:1的比例。
43.  避免一个接口中只有一个成员。
44.  尽量使每个接口中包含3-5个成员。
45.  接口中的成员不应该超过20个。
a)  实际情况可能限制为12个
46.  避免接口成员中包含事件。
47.  避免使用抽象方法而使用接口替换。
48.  在类层次中显示接口。
49.  推荐使用显式的接口实现。
50.  从不假设一个类型兼容一个接口。Defensively query for that interface.
SomeType obj1;
IMyInterface obj2;

/* 假设已有代码初始化过obj1,接下来 */
obj2 = obj1 as IMyInterface;
if (obj2 != null)
{
   obj2.Method1();
}
else
{
   //处理错误
}  
51.  表现给最终用户的字符串不要使用硬编码而要使用资源文件替换之。
52.  不要硬编码可能更改的基于配置的字符串,比如连接字符串。
53.  当需要构建长的字符串的时候,使用StringBuilder不要使用string
54.  避免在结构里面提供方法。
a)  建议使用参数化构造函数
b)  可以重裁操作符
55.  总是要给静态变量提供静态构造函数。
56.  能使用早期绑定就不要使用后期绑定。
57.  使用应用程序的日志和跟踪。
58.  除非在不完全的switch语句中否则不要使用goto语句。
59.  在switch语句中总是要有default子句来显示信息(Assert)。
int number  = SomeMethod();
switch(number)
{
   case 1:
      Trace.WriteLine(“Case 1:”);
      break;
   case 2:
      Trace.WriteLine(“Case 2:”);
      break;
   default :
      Debug.Assert(false);      
     break;
}
60.  除非在构造函数中调用其他构造函数否则不要使用this指针。
// 正确使用this的例子
public class MyClass
{
   public MyClass(string message )
   {}
   public MyClass()  : this(“hello”)
   {}
}
61.  除非你想重写子类中存在名称冲突的成员或者调用基类的构造函数否则不要使用base来访问基类的成员。
// 正确使用base的例子
public class Dog
{
   public Dog(string name)
   {}
   virtual public void Bark( int howLong)
   {}
}
public class GermanShepherd : Dog
{
   public GermanShe pherd(string name): base (name)
   {}
   override public void Bark(int  howLong) 
   {
      base .Bark(howLong);  
   }
}
62.  基于模板的时候要实现Dispose()和Finalize()两个方法。
63.  通常情况下避免有从System.Object转换来和由System.Object转换去的代码,而使用强制转换或者as操作符替。
class SomeClass
{}
//避免:
class MyClass 
{   
   void SomeMethod(T t)   
   {
      object temp = t;      
      SomeClass obj = (SomeClass)temp;    
   }
}
// 正确:
class MyClass where T : SomeClass
{   
   void SomeMethod(T t)   
   {
      SomeClass obj = t;   
   }
}
64.  在一般情况下不要定影有限制符的接口。接口的限制级别通常可以用强类型来替换之。
public class Customer
{…}
//避免:
public interface IList where T : Customer 
{…}
//正确:
public interface ICustomerList : IList 
{…}
65.  不确定在接口内的具体方法的限制条件。
66.  总是选择使用C#内置(一般的generics)的数据结构。
2005年01月14日
From: http://www.lagash.com/english/mbi/appsenmbi.html

Entities

Entities represent the business objects of an organization. They provide information and code behaviour. For example in a Bank the “Savings Account” or the “Cusomter” are Business Entities. Entities have a state component that manages it’s persistence and a dynamic component given by the operations to be performed upon them. In an Account, the account number, the currency, the opening date, the owner, are properties or attributes of the Entity. A transference, a debit, a credit, the comissions are actions to be performed on one or more Entities.

The entities according to this model are not implemented with a single .Net class, but with a set of them, linked logically in a so called “assembly”.

An entity contains at least three subcomponents:

  • A set of Actions that constitute it’s public interface. The way of invoking Actions is through Request and Response messages. The invocation of an action must leave the system in a consistent state.
  • A set of Adapters or Connectors, providing access to the persistent data repositories. A connector allows, for instance, to access a CICS transaction, data in a CRM as Siebel, or to SQL Server
  • Data managers, that coordinate the access from Actions. These mangers can be simple “wrappers” to invoke the connectors or a complex hierarchy of classes.

This model of loosly coupled pieces has several advantages:

  • They result on being highly scalable applications because each one of these components can be physically distributed in different places being their access tranparent through Microsoft.Net communication mechanisms without losing the necessary logic union that preserves the Entity.
  • Because the interaction is based on messages, the state administration of the components is minimized, delegating this responsibility in the persistent repositories, which are optimized for this task and on the Activities.
  • The construction effort can easily be distributed in different work groups, because the integration in greatly facilitated having a common based architecture.
  • The logic components are identical, independent from the Activities that invoke them, because the interaction is done through Channel Adapters.
  • The powerfull .NET versioning mechanisms are used, facilitating the reuse and coexistence of applications of different generations.
2005年01月08日
Summary

这里介绍了ICE的五个服务

        Ice为分布式开发提供了技术完善的客户-服务平台。实际上,现实的应用不仅仅只需要具备远程通讯能力,通常的,还需要随需启动服务,把代理分布到客户端,分发异步事件,配置应用,发布补丁等等。


        Ice自带了一些服务,这些服务具备了上面所说的特征和一些其它的特征。这些服务实现以服务器的形式实现并向你的应用提供服务。他们分别是:


1、IcePack


         IcePack是Ice的定位服务。当使用间接绑定时,用来将符号化的适配器名称转换为协议-地址对。除了定位服务之外,IcePack还提供了如下的服务:


  • IcePack允许你注册一个自动启动的服务:即当客户端进行请求时,服务器不需要处于运行状态,只要第一个客户端进行请求时,服务会自动启动。
  • IcePack支持脚本描述部署,可以轻易的配置包含了若干个服务的复杂的应用
  • IcePack提供了简单的对象查找服务,允许客户端获取他们感兴趣的对象代理。


2、IceBox


        IceBox是一个简单的应用服务器,它可以协调多个应用组件启动和停止。


        应用组件可以用动态链接库的形式发布而不是一个进程。这就减轻了系统的负载。例如,你可以在一个JVM中运行若干个应用组件而不是有多个进程,每一个进程都有自己的JVM。


3、IceStorm


        IceStorm是一个发布-订阅服务,它减除了客户端和服务器的耦合度。本质上说,IceStorm作为一个事件分发的交换机运行。发布者将事件发给服务,IceStorm按照顺序将事件传递给订阅者。使用这种方法,一个事件发布者就可以把一个事件发布给多个订阅者。事件按照主题分类,订阅者可以指定他们感兴趣的主题。只有订阅者感兴趣的主题才会发送给订阅者。服务允许指定服务的质量,从而允许应用在可伸缩性和性能之间进行适当的折中。


        如果你需要将信息发布到大量的应用组建,那么IceStorm是一个不错的选择。(一个很典型的例子就是股票报价的应用)。IceStorm减除了信息的发布者和订阅者之间的耦合,同时也能重新发布已经发布的信息。另外,IceStorm可以作为联合服务运行,即多个服务的实例可以运行在不同的机器上,从而降低了CPU的负载。


4、IcePatch


        IcePatch是一个软件补丁服务。它允许你轻松的把软件的更新发布给客户。客户连接到IcePatch然后请求更新一个特定的应用。服务就自动检查客户软件的版本然后下载需要更新的组件。而这些下载的组件都是放在一个压缩包里的,从而减少了带宽的占用。软件补丁也可以通过结合Glacier服务发布,这样可以让只有经过授权的客户才能下载软件更新。


5、Glacier


        Glacier是Ice防火墙服务:它允许客户和服务器通过防火墙安全的通讯。客户-服务器的通讯通过使用公钥认证完全加密,并且通讯是双向的。Glacier提供了相互认证和安全的会话管理支持。


http://www.cnblogs.com/iaxes/articles/71411.html

原文作者信息

    • Justin Greenwood
    • MyGeneration Software
    • http://www.mygenerationsoftware.com/
    • October 7, 2004

系统需求:

  • Microsoft Windows 2000/XP
  • Microsoft .Net Framework 1.1/更高
  • MDAC 2.7/更高
  • MyGeneration

概观

MyGeneration目前使用了两种脚本引擎,一个是Microsoft Scripting Engine,它提供了JScript和VBScript的生成支持;另一个是 DotNetScript ,它提供了 VB.NET 和 C# 的支持。 DotNetScript 不像Microsoft Scripting Control那样的真正的脚本。实际上,它在运行时编译代码,然后利用编译后的.NET Assembly执行代码。这个教程通过例子说明使用 DotNetScript 开发MyGeneration模板的赞成与反对的理由。在这个例子中,我将使用C#和MS SQL中附带的Northwind数据库。

创建一个新的C#模板

  • 打开MyGeneration
  • 通过File->New->C# Template创建一个新的模板
  • 点击属性按钮编辑模板的属性
  • 如下图,填充模板的属性
  • 保存模板




研究默认的模板代码
默认的模板主体代码:

不像 JScript 或VBScript,C#的的模板代码相对较少。这个默认的代码是非常重要的。一个C#模板必须有一个继承了 DotNetScriptTemplate 的名为 GeneratedTemplate 的类。 MyGeneration 通过实例化 GeneratedTemplate ,并调用Render方法开始生成过程。几乎大部分的模板开发工作都在Render方法里面完成。试试执行这个模板,你将会看到literal content goes here作为输出出现。

<%
 
public class GeneratedTemplate : DotNetScriptTemplate
 
{
        
public GeneratedTemplate(ZeusContext context) : base(context) {}


        
public override void Render()
        
{
 
%>
 Literal content goes here.
 
<%
        }



 }

 
%>

默认的UI接口代码:

在默认的模板的接口代码中,同样需要一个名为GeneratedGui的,继承DotNetScriptGui的强制类。如同模板主体代码的Render方法一样, MyGeneration 将调用Setup方法开始显示用户接口并收集输入。

public class GeneratedGui : DotNetScriptGui
 
{
        
public GeneratedGui(ZeusContext context) : base(context) {}


        
public override void Setup()
        
{
        }

 }

获取输入:用户接口的代码块

在这个例子中,用户将通过接口选择一个表。这个是接口代码块的擅长的工作。用户接口获取的输入数据,将在模板主体代码中用来生成代码。
使用MyGeneration的接口代码:

public class GeneratedGui : DotNetScriptGui
 
{
        
public GeneratedGui(ZeusContext context) : base(context) {}


        
public override void Setup()
        
{
                ui.Title 
= .NetScript C# Sample: Java Class;
                ui.Width 
= 340;
                ui.Height 
= 200;


                
// Setup Database selection combobox.
                GuiLabel label_d = ui.AddLabel(lblDatabasesSelect a database:Select a database in the dropdown below.);
                GuiComboBox cmbDatabases 
= ui.AddComboBox(databaseNameSelect a database.);


                
// Setup Tables selection multi-select listbox.
                GuiLabel label_t = ui.AddLabel(lblTablesSelect table:Select table from the combobox below.);
                GuiComboBox cmbTables 
= ui.AddComboBox(tableNameSelect a table.);


                
// bind data to the controls
                cmbDatabases.BindData(MyMeta.Databases);
                cmbDatabases.SelectedValue 
= MyMeta.DefaultDatabase.Name;
                cmbTables.BindData( MyMeta.Databases[cmbDatabases.SelectedValue].Tables );

                
// Attach the onchange event to the cmbDatabases control.
                cmbDatabases.AttachEvent(onchangecmbDatabases_onchange);

                ui.ShowGui 
= true;
        }



        
public void cmbDatabases_onchange(GuiComboBox control)
        
{
                GuiComboBox cmbDatabases 
= ui["databaseName"as GuiComboBox;
                GuiComboBox cmbTables 
= ui["tableName"as GuiComboBox;


                cmbTables.BindData( MyMeta.Databases[cmbDatabases.SelectedValue].Tables );
        }

 }

使用.NET Windows Form API的接口代码:
下面的代码是不使用 MyGeneration API的替换方案,它可以达到与上面的代码同样的目的。

<%#REFERENCE System.Windows.Forms.dll %>
 
<%#NAMESPACE System.Windows.Forms %>
 
public class GeneratedGui : DotNetScriptGui
 
{
        
public GeneratedGui(ZeusContext context) : base(context) {}


        
public override void Setup() 
        
{
                AcquireInputForm form 
= new AcquireInputForm(MyMeta, input); 


                
if (form.ShowDialog() != DialogResult.OK) 
                
{
                        ui.IsCanceled 
= true;
                }

        }

 }



 
public class AcquireInputForm : Form
 
{
        
private ComboBox cboDatabases = new ComboBox();
        
private ComboBox cboTables = new ComboBox();
        
private Button btnOk = new Button();
        
private dbRoot meta;
        
private IZeusInput input;


        
public AcquireInputForm(dbRoot mymeta, IZeusInput zin)
        
{
                
this.meta = mymeta;
                
this.input = zin;


                
this.BindComboBox(cboDatabases, meta.Databases);
                cboDatabases.SelectedItem 
= meta.DefaultDatabase.Name;
                cboDatabases.Top 
= 10; cboDatabases.Left = 10; cboDatabases.Width =  200;
                cboDatabases.SelectedIndexChanged 
+= new EventHandler(cboDatabases_SelectedIndexChanged);


                
this.BindComboBox(cboTables, meta.DefaultDatabase.Tables);
                cboTables.Top 
= 50; cboTables.Left = 10; cboTables.Width =  200;


                btnOk.Text 
= Ok;
                btnOk.Top 
= 100; btnOk.Left = 10; btnOk.Width = 200;
                btnOk.Click 
+= new EventHandler(btnOk_Click);


                
this.Controls.AddRange( new Control[] {cboDatabases, cboTables, btnOk} );
                
this.Text = .NetScript C# Sample: Java Class;
                
this.Width = 230;
                
this.Height = 160;
        }



        
public void cboDatabases_SelectedIndexChanged(object sender, EventArgs args) 
        
{
                
this.BindComboBox(
                                cboTables, 
                                meta.Databases[ cboDatabases.SelectedItem.ToString() ].Tables 
                        );
        }



        
public void btnOk_Click(object sender, EventArgs args) 
        
{
                
if ((cboDatabases.SelectedIndex >= 0&&
                        (cboTables.SelectedIndex 
>= 0)) 
                
{
                        input[
"databaseName"= cboDatabases.SelectedItem.ToString();
                        input[
"tableName"= cboTables.SelectedItem.ToString();
                        
this.DialogResult = DialogResult.OK;
                        
this.Close();
                }

                
else 
                
{
                        MessageBox.Show(
Fill out the required fields.. PLEASE??);
                }

        }



        
private void BindComboBox(ComboBox cbo, IEnumerable myMetaCollection)
        
{
                cbo.Items.Clear();
                
foreach (INameValueItem item in myMetaCollection)
                
{
                        cbo.Items.Add(item.ItemValue);
                }

        }

 }

 

模板主体

模板主体是生成代码的主要执行地。下面讲解了我如何生成代码的步骤。

1、将期望输出的代码放入到Render的方法中如下的代码,你将看到我将要生成的类。这几乎都是当我要生成一个模板是必做的第一件事情。

<%
 
public class GeneratedTemplate : DotNetScriptTemplate
 
{
        
public GeneratedTemplate(ZeusContext context) : base(context) {}


        
public override void Render()
        
{
                
string databaseName = input["databaseName"].ToString();
                
string tableName = input["tableName"].ToString();
 
%>
/*
 * Employee.java
 *
 * Created on September 23, 2002, 12:59 PM
 
*/



 package com.mygeneration.sample;


 import java.sql.
*;


 import com.mygeneration.businessobjects.
*;
 import com.mygeneration.dataaccess.
*;


 
public class Employee extends BizObj
 
{
    
public Employee() 
    
{
    }



    
// EmployeeID
    public String getEmployeeID()
    
{
        
return getString(EmployeeSchema.EmployeeID.getFieldName());
    }



    
public void setEmployeeID(String employeeID)
    
{
        setString(EmployeeSchema.EmployeeID.getFieldName(), employeeID);
    }
    
 }
<%
        }



 }

 
%>

2、添加动态代码把动态的代码添加到模板中,替换掉类名、属性名称以及数据类型。

<%
 
public class GeneratedTemplate : DotNetScriptTemplate
 
{
        
public GeneratedTemplate(ZeusContext context) : base(context) {}


        
public override void Render()
        
{
                
string databaseName = input["databaseName"].ToString();
                
string tableName = input["tableName"].ToString();


                IDatabase database 
= MyMeta.Databases[databaseName];
                ITable table 
= database.Tables[tableName];
 
%>/*
 * <%= table.Alias %>.java
 *
 * Created on <%= DateTime.Now.ToString() %>
 
*/



 package com.mygeneration.sample;


 import java.sql.
*;


 import com.mygeneration.businessobjects.
*;
 import com.mygeneration.dataaccess.
*;


 
public class <%= table.Alias %> extends BizObj
 
{
    
public <%= table.Alias %>() 
    
{
    }

 
<%
                
foreach (IColumn column in table.Columns)
                
{
                        
string datatype = this.GetJavaType(column);
 
%>    
    
// <%= column.Alias %>
    public <%= datatype %> get<%= column.Alias %>()
    
{
        
return get<%= datatype %>(<%= table.Alias %>Schema.<%= column.Alias %>.getFieldName());
    }



    
public void set<%= column.Alias %>(<%= datatype %> m_<%= column.Alias %>)
    
{
        
set<%= datatype %>(<%= table.Alias %>Schema.<%= column.Alias %>.getFieldName(), m_<%= column.Alias %>);
    }

 
<%
                }

 
%>    
 }
<%
        }



        
private string GetJavaType(IColumn column)
        
{
                
string sqlServerType = column.DataTypeName;
                
int charLength = column.CharacterMaxLength;


                
switch (sqlServerType) 
                
{
                        
case bit:
                                
return Boolean;
                        
case decimal:
                        
case float:
                        
case numeric:
                        
case money:
                        
case smallmoney:
                        
case real:
                                
return Decimal;
                        
case tinyint:
                        
case smallint:
                        
case int:
                        
case bigint:
                                
return Integer;
                        
case smalldatetime:
                        
case datetime:
                                
return Timestamp;
                        
case varchar:
                        
case char:
                        
case nvarchar:
                        
case nchar:
                        
case text:
                                
if (charLength == 1)
                                        
return Character;
                                
else
                                        
return String;
                        
default:
                                
return Object;
                }

        }

 }

 
%>

总结

使用 DotNetScript ,你将会把 MyGeneration 的模板开发提升到一个新的水平,提供更强大的功能以及能开发更复杂的系统。

刚看到NHibernate推出0.6版了,并且是Beta哦,看来上半年1.0正式版有望了。:)

主要变化有:
- Added support for proxy=”" on classes.  proxy=”" must either specify an Interface or the properties that need to be proxied have to be virtual.
- Added a configuration parameter “hibernate.prepare_sql” to turn on or off calls to IDbCommand.Prepare().
- Added NHibernate Type for System.SByte. (Sergey Koshcheyev)
- Added support for mapping subclasses and joined-subclasses in different files through addition of extends attribute. (Andrew Mayorov)
- Added support for LIMIT to MySQLDialect. (Sergey Koshcheyev)
- Improved error messages when IDbCommand and IDbConnection can’t be found by the IDriver.
- Improved error message when mapped class is missing a constructor with no args.
- Fixed problem with spaces in sql generated from hql and MySql.
- Fixed bug with Configuration when there is a class without a namespace.
- Fixed bug with Sql generated for an IN clause that contains a class/subclass with a discriminator-value=”null”.
- Fixed potential threading problem with QueryTranslator.
- Modified logging in Transaction to not generate as many messages.
- Modified how exceptions are rethrown so call stack of original exception is not lost.
- Moved NHibernate.Tasks and NHibernate.Tool.hbm2net to the NHibernateContrib package.
- Removed DbType {get;} from IUserType.

MyGeneration -又一个 O/R Mapping 的工具和代码产生工具,可以产生Gentle.NETNHibernate的代码

2005年01月06日

Web编程的一个基本任务就是对用户输入到表单中的值进行检查。传统的ASP编程在这一方面并没有提供太大的支持,而是把相应的检查工作留给程序开发人员来设计和编写自己的表单检查机制。

幸运的是,ASP.NET对表单检查进行了相当大的改进。对初学者来说,以事件为基础的、以UI控件为中心的WebForm编程模式大大简化了表单检查的任务。不过,ASP.NET在原有基础之上更进一步,通过一整套服务器控件直接支持表单检查,从而几乎完全消除了自己建立表单检查机制的必要。本文的主旨即是介绍和演示ASP.NET随带的检查服务器控件。

检验控件层次

ASP.NET检验服务器控件(validation server control)同TextBoxLabel等Web服务器控件一道位于System.Web.UI.WebControls名称空间之下。ASP.NET提供了6种检验控件,如图A所示:

图A

ASP.NET检验控件

ValidationSummary控件并不执行具体的表单值检验工作。它的功能是总结页面内其他检验控件发出的错误消息。在本文的其他部分,当我提到检验控件的时候,我指的是那些执行具体检验任何的控件,也就是除了ValidationSummary之外的其他控件。

检验控件直接或者间接派生自抽象的BaseValidater类,该类又是从Label控件派生的。你可能会觉得奇怪,检验控件怎么会从Label派生呢?很快我们就会知道原因何在了。

检验

检验控件对页面上输入服务器控件的值进行检查,从而判断出这些值是否符合特定的条件。被检查的输入控件由检验控件的ControlToValidate属性设定。你可以对检验控件编程令其调用Validate方法对数据控件的输入值进行检查,如果检验结果符合条件则该方法会把检验控件的IsValid属性设置为true,否则设置为false。你可以设置页面上的检验控件调用Page.Validate方法对所有输入控件的输入值进行检查。

Page.IsValid属性在页面内所有检验控件的检查都成功的情况下设置为true否则设置为false。假如按下了某个按钮控件,而且该控件的CausesValidation属性设置为true,那么Page.Validate方法即被调用。Reset或者clear按钮的CausesValidation属性默认设置为 false。假如页面上任何检验空间的IsValid设置为false那么按钮单击事件即被屏蔽。

如果浏览器支持ECMAScript 1.2 (JScript) 和Document Object Model (DOM) (兼容Internet Explorer 4及以后版本),那么检验控件会执行客户端脚本在客户机上进行表单检查工作而不会通过服务器进行迂回检查。这样做可以给用户提供给及时的反馈。为了对浏览器提供强度更大的支持和防止用户旁路表单检查,当页面提交之后服务器端也会执行表单检查。客户端检查可以禁用,方法是把检验控件的EnableClientScript属性设置为false。你还可以禁用页面内所有检验控件的客户端表单检查,只需要在@Page指示符内设置属性ClientTarget=”downlevel”即可。

在检查不通过的情况下,检验控件的Text属性会在页面内检验控件所在的位置显示出来,其外观形式就如同一个标签。假如没有设置Text属性则显示ErrorMessage属性。一旦检验不通过,ErrorMessage属性也会显示在ValidationSummary控件内。假如检验控件没有设置ErrorMessageValidationSummary上什么都不会显示。一般原则是摘要消息或者错误提示可以采取设置Text属性的方式,而较长的说明则采取设置ErrorMessage属性的方式。

不同的检验控件测试的条件是不同的:

  • RequiredFieldValidator—如果输入控件中已经输入了值则检验成功。
  • RangeValidator—如果输入控件的值处于MaximumValueMinimumValue属性限定的范围之内则检验成功。Type属性设置MaximumValue MinimumValue的数据类型,而输入控件内的值则在执行范围比较之前进行转换。
  • RegularExpressionValidator—如果输入控件内的值匹配ValidationExpression属性设置的正则表达式则检验成功。
  • CompareValidator—该控件通过其Operator属性执行多种类型的检查。DataTypeCheck运算符只检查输入控件内的值是否可以转换为Type属性设置的数据类型。关系运算符,比如Equal或者GreaterThan把输入控件内的值同某静态值(由ValueToCompare属性设置)或者其他控件的值(由ControlToCompare属性设置)进行比较。
  • CustomValidator—该控件可以让你通过对CustomValidator.ServerValidate事件的处理执行自己的唯一性检查。在调用CustomValidator.Validate时会触发该事件。事件处理器可以检查你希望得到的结果并把ServerValidateEventArgs事件参数的IsValid属性设置为检验控件的状态。ServerValidate事件处理器可以通过OnServerValidate属性设置。通过ClientValidationFunction属性设置客户端脚本函数即可启用客户端检验。
2005年01月03日

这是缓存的问题,
在html里添加<%@ OutPutCache Location=”None”%>
ASP.NET 允许您在具有 HTTP 1.1 功能的机制上缓存动态页的整个响应内容,这些机制指浏览器、代理服务器和您的应用程序所驻留的 Web 服务器等。这为您提供了一个强有力的方式来提高 Web 应用程序的性能。此技术叫做输出缓存,它允许从缓存满足后面的对特定页的请求,这样当后面的请求发生时就不需要运行最初创建页的代码。使用该技术来缓存站点中最经常访问的页可以充分地提高 Web 服务器的吞吐量(通常以每秒的请求数计算)。
当操作页的输出缓存时,您可以选择高级别的声明性 API 或低级别的编程 API。您可以通过将@ OutputCache 指令包括在该页的 .aspx 文件中使用前者。@ OutputCache 指令可以满足当要缓存页输出时几乎所有的一般需求。下面的指令(当包括在 .aspx 文件中时)为动态生成页的缓存输出设置 60 秒的到期时间。
<%@ OutputCache Duration=”60″ VaryByParam=”None” %>

2004年12月28日

金羊网 2004-12-09 09:00:24
新快报讯(记者周继坚)广州新人办理婚姻登记将不受周末、节假日婚姻登记机关放假的影响!记者昨日从广州市民政部门获悉,广州市目前已经在五个老区试点,实行婚姻登记机关周末和法定节假日照常办理登记业务。

据了解,广东省民政厅今年10月率先在深圳市宝安区进行试点,在周末和法定节假日增加1-2天工作时间,所有申请办理婚姻登记的居民可以在当天将手续办理完毕。

据悉,广州的试点工作已经在天河、越秀、荔湾、东山、海珠等五区展开。但各个婚姻登记处的工作人员没有增加,目前尚无法进行大量的婚姻登记业务,确实有需要的市民可以先行预约。