您的位置:首页 > 其它

见到了“公司”定义一个Company类,那么见到了“字段”是不是也可定义一个Column类?

2010-01-07 22:48 483 查看
  既然见到了公司,我们可以定义一个Class Company ,那么我们见到了字段,是不是也可以定义一个Class ColumnInfo呢?



公司的描述信息类:




代码

public class Company

{

public int CompanyId { get; set; }

public string CompanyName { get; set; }

public string Province { get; set; }

public string City { get; set; }

public string Address { get; set; }

public string HomePage { get; set; }

public string Phone { get; set; }

}





字段的描述信息类




代码

public class ColumnsInfo

{

#region 属性——字段的基本信息的描述

#region 字段编号 _ColumnID

private int _ColumnID = 0;

/// <summary>

/// 配置信息里面的字段的标识

/// 表ID + 四位序号 组成。一旦生成不建议修改。

/// </summary>

public int ColumnID

{

get { return _ColumnID; }

}

#endregion

#region 字段所在的表的编号 _TableID

private int _TableID = 0;

/// <summary>

/// 字段所在的表的编号

/// </summary>

public int TableID

{

get { return _TableID; }

}

#endregion

#region 字段类型 _ColumnKind

private int _ColumnKind = 1;

/// <summary>

/// 字段类型

/// 1:正常;2:主键;3:外键

/// </summary>

public int ColumnKind

{

get { return _ColumnKind; }

}

#endregion

#region 字段名 _ColSysName

private string _ColSysName = "";

/// <summary>

/// 数据库里的字段名称

/// </summary>

public string ColSysName

{

get { return _ColSysName; }

}

#endregion

#region 显示给客户看的字段名 _ColName

private string _ColName = "";

/// <summary>

/// 显示给客户看的名称

/// </summary>

public string ColName

{

get { return _ColName; }

}

#endregion

#region 字段类型 _ColType

private string _ColType = "";

/// <summary>

/// 字段类型,int、nvarchar、datetime 等

/// </summary>

public string ColType

{

get { return _ColType; }

}

#endregion

#region 字段大小 _ColSize

private Int32 _ColSize = 0;

/// <summary>

/// 字段大小

/// </summary>

public Int32 ColSize

{

get { return _ColSize; }

}

#endregion

//表单控件专用

#region 是否保存,表单控件用 _IsSave

private bool _IsSave = true;

/// <summary>

/// 是否要把控件的值保存到数据库里面。True:保存,False:不保存

/// </summary>

public bool IsSave

{

get { return _IsSave; }

}

#endregion

#endregion

}





  定义Company是为了保存公司相关的一些信息,那么定义ColumnInfo是为了什么呢?自然是要记录字段的相关信息了,比如字段名、字段大小、字段类型等,然后等到用的时候就可以直接获取了。

  我知道有的方法是采用XML来记录这些信息,然后和Company这样的类作对应,还有个方法是采用“特性”,把这些信息记录到特性里面。那么我为什么要定义一个ColumnInfo来记录这些信息呢?

  前两种方法有两个特点:编译前确定、类爆炸。

  

  前两种方法都是以面向对象为主,先根据现实里的情况来定义实体类,然后在想办法把实体类和数据库对应上。在.net里面是在运行时类的结构就不能在变化了。如果要改变类的结构或者改个类名,都需要修改代码然后重新编译才行。

  这样的话对于信息管理的项目就很麻烦了。比如公司信息,今天调研的时候客户说只需要六个属性就可以了,但是第二天可能就要提出来在加上一个公司地址。等到了上线运行的时候又提出来需要加上电子信箱。当然了这些都是小修小改,比这麻烦的改动大家也都见得多了吧。

  应对这样的需求变化,就需要修改实体类。虽然有代码生成器,虽然有各种ORM,但是类的定义还是要改的吧。而且修改之后必须重新编译,更新文件才行。

我是比较烦修改代码的,改来改去就改乱了。



  类爆炸,见到了员工定义一个Personal,见到了公司定义一个Company……这就是类爆炸。一个项目下来,几十个、上百个实体类,这些实体类都负责什么功能呢?有一大半都是只实现了增删改查,就完成任务了,说白了就是传递一下数据。如果只是为了传递数据而定义这么多的实体类,在我看来真的是很浪费的。很多不必要的修改量也是由此而产生的。

  当然了如果您定义实体类是为了实现很复杂的业务逻辑的话,那就另当别论了。

如何解决呢?我们先看看我们想要达到什么目的?信息的增删改查。那么信息要放在哪里呢?关系型数据库(如果您的数据不是放在关系型数据库的话,那么不在本次讨论的范围内)。不管是员工信息、公司信息还是产品信息,都是数据库里的一条条数据。既然都是数据,那么就都要和字段打交道。那么我们是不是可以从这个角度来抽象一下呢?



  ColumnInfo就是我的抽象的结果。每一个字段都是一个实例,比如Company的CompanyName是一个实例,City又是一个实例,这些实例放在一个集合(我采用了字典Dictionary)里面,就可以表达一个完整的含义。



  这样不管信息如何变化,如何增加都不需要修改ColumnInfo的结构,这样就避免的类爆炸,当然换成了“实例爆炸”,不过实例可是要比类好管理多了。

ColumnInfo是通过属性值来区分的,那么就意味着我可以在运行时决定属性值。像字段名有变化这样的修改,就完全不用修改代码。

这还带来了另外一个优点。由于是以字段为最小单位,字段可以灵活的组合,同一个字段既可以放在集合A里面,又可以放在集合B里面。这样就解决了字段复用的问题。



延伸:

  字段在添加、修改的时候需要对应一个控件,比如CompanyName要对应一个文本框,City要对应一个下拉列表框。那么我们是不是可以把控件也描述一下,并且把字段和控件对应起来。这样我们就可以在表单页面里根据这些信息来动态生成各种控件了。

【类图】







  以字段信息为父类,生成(派生)了两个子类:列表,表单。表单又生成了两个子类:添加/修改,查询。为了准确描述各种控件各自特点的信息,又定义了一个ControlInfo,在这里定义控件的特殊属性。



  根据“表单类”可以绘制表单,实现添加、修改数据的功能,或者是查询数据时候的查询条件的录入。

  列表类可以绘制表格(<table>),还可以导出Excel。

  FunctionInfo是功能节点的描述信息,里面包含三个类:分页信息(相当于显示数据和查询数据);添加、修改、删除用信息;页面信息。



  这就是自然框架的元数据,也就是描述信息,是自然框架的“灵魂”。

  自然框架的元数据就相当于盖大楼用的图纸,乐队演奏音乐用的乐谱。



GridInfo类的代码:




代码

/// <summary>

/// 列表里的描述信息

/// </summary>

public class GridInfo : ColumnsInfo

{

#region 属性

#region TD的宽度 _ColWidth

private int _ColWidth = 0;

/// <summary>

/// td的宽度。0:不限制宽度

/// </summary>

public int ColWidth

{

get { return _ColWidth; }

}

#endregion

#region TD的对齐方式 _ColAlign

private string _ColAlign = "";

/// <summary>

/// 横向的对齐方式 left center right

/// </summary>

public string ColAlign

{

get { return _ColAlign; }

}

#endregion

#region 格式化 _Format

private string _Format = "";

/// <summary>

/// 格式化的方式。空字符串表示不格式化

/// </summary>

public string Format

{

get { return _Format; }

}

#endregion

#region 最多显示的字符数

private int _MaxLength = 0;

/// <summary>

/// 最多显示多少个字符。0:不限制。注:一个汉字占两个字符

/// </summary>

public int MaxLength

{

get { return _MaxLength; }

}

#endregion

#endregion



}





FormInfo类的代码

/// <summary>

/// 表单的描述信息

/// </summary>

public class FormInfo : ColumnsInfo

{

#region 属性

//添加修改、查询共用的属性

#region 控件类型 _ControlKind

private int _ControlKind = 201;

/// <summary>

/// 字段对应的控件类型(编号),比如 201(表示单行文本)

/// </summary>

public int ControlKind

{

get { return _ControlKind; }

}

#endregion

#region 控件的描述信息 _ControlInfo

private ControlInfo _ControlInfo ;

/// <summary>

/// 控件的描述信息,宽、高、最大字符数等。

/// </summary>

public ControlInfo ControlInfo

{

get { return _ControlInfo; }

}

#endregion

#region 默认值 _DefaultValue

private string _DefaultValue = "";

/// <summary>

/// 默认值

/// </summary>

public string DefaultValue

{

get { return _DefaultValue; }

}

#endregion

#region 控件状态 _ControlState

private string _ControlState = "";

/// <summary>

/// 控件的状态。1:正常;2:只读;3:不可用;4:隐藏

/// </summary>

public string ControlState

{

get { return _ControlState; }

}

#endregion

//布局,也是共用的

#region 是否合并到上一个TD _TDStart

private Int32 _TDStart = 0;

/// <summary>

/// 是否合并到上一个TD。0:不合并;其他:合并后添加几个空格(用于占位);

/// </summary>

public Int32 TDStart

{

get { return _TDStart; }

}

#endregion

#region 是否把下一个字段合并上来 _TDEnd

private bool _TDEnd = false;

/// <summary>

/// 是否把下一个字段合并上来。false:不合并;true:合并

/// </summary>

public bool TDEnd

{

get { return _TDEnd; }

}

#endregion

#region 一个控件占用几个TD _TDColspan

private Int32 _TDColspan = 1;

/// <summary>

/// 记录一个控件占用几个TD

/// </summary>

public Int32 TDColspan

{

get { return _TDColspan; }

}

#endregion

#endregion

}



ModInfo类的代码:




代码

/// <summary>

/// 添加、修改的描述信息

/// </summary>

public class ModInfo : FormInfo

{

#region 属性



#region 帮助信息 ControlColHelp

private string _ControlColHelp = "";

/// <summary>

/// 帮助信息

/// </summary>

public string ControlColHelp

{

get { return _ControlColHelp; }

}

#endregion

#region 帮助信息的位置 _ControlHelpStation

private int _ControlHelpStation = 1;

/// <summary>

/// 帮助信息的位置。1:不显示;2:最面;3:右面

/// </summary>

public int ControlHelpStation

{

get { return _ControlHelpStation; }

}

#endregion

#region 控件在aspx文件里的ID名称 _ControlID

private string _ControlID = "";

/// <summary>

/// 控件在aspx文件里的ID名称,手动绘制页面的时候使用。

/// </summary>

public string ControlID

{

get { return _ControlID; }

}

#endregion

#region 验证方式,_ControlCheckKind

private int _ControlCheckKind = 101;

/// <summary>

/// 验证方式

/// </summary>

public int ControlCheckKind

{

get { return _ControlCheckKind; }

}

#endregion

#region 自定义验证方式,表单控件用 _CustomerCheckKind

private string _CustomerCheckKind = "";

/// <summary>

/// 自定义验证方式,即正则表达式

/// </summary>

public string CustomerCheckKind

{

get { return _CustomerCheckKind; }

}

#endregion

#region 验证信息,表单控件用 _CheckTip

private string _CheckTip = "";

/// <summary>

/// 未通过验证的提示信息

/// </summary>

public string CheckTip

{

get { return _CheckTip; }

}

#endregion

#endregion

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐