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

简介:   既然见到了公司,我们可以定义一个Class Company ,那么我们见到了字段,是不是也可以定义一个Class ColumnInfo呢?   公司的描述信息类: 代码 public class Company     {         public int Comp...

 

  既然见到了公司,我们可以定义一个Class Company ,那么我们见到了字段,是不是也可以定义一个Class ColumnInfo呢?

 

公司的描述信息类:

img_405b18b4b6584ae338e0f6ecaf736533.gif 代码
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 ; }
}

 

 

字段的描述信息类

img_405b18b4b6584ae338e0f6ecaf736533.gif 代码
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类的代码:

img_405b18b4b6584ae338e0f6ecaf736533.gif 代码
///   <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类的代码:

img_405b18b4b6584ae338e0f6ecaf736533.gif 代码
///   <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
}

 

 

 

相关文章
|
27天前
mongoTemplate 嵌套对象包含id
mongoTemplate 嵌套对象包含id
17 0
|
28天前
|
SQL 存储 Oracle
为什么 GROUP BY 之后不能直接引用原表中的列
为什么 GROUP BY 之后不能直接引用原表中的列
27 1
|
7月前
|
Web App开发 API 开发者
关于 SAP UI5 Context.prototype.delete 方法的输入参数 Group ID 的细节
关于 SAP UI5 Context.prototype.delete 方法的输入参数 Group ID 的细节
60 0
|
10月前
|
消息中间件 缓存 数据库
A和B接口同时修改table字段,无法确认调用顺序
在互联网应用开发中,经常会碰到多个接口同时需要修改数据库表字段的情况。然而,由于无法确认接口调用的顺序,可能会导致数据冲突和一致性问题。本文将介绍一种解决这一问题的方法,通过合理的设计和技术手段,确保同时修改table字段的操作能够顺利进行,数据一致性得到保障。
91 0
A和B接口同时修改table字段,无法确认调用顺序
|
10月前
|
Java
定义Student类
定义Student类
88 0
|
SQL 分布式计算 大数据
Column 对象_操作_别名和类型 | 学习笔记
快速学习 Column 对象_操作_别名和类型
77 0
Column 对象_操作_别名和类型 | 学习笔记
重构——29以数据类取代记录(Replace Record with Data Class)
以数据类取代记录(Replace Record with Data Class):你需要面对传统编程环境中的记录结构;为该记录创建一个“哑”数据对象
1511 0
SAP Spartacus b2b table,通过listService的table type字段来控制要加载的数据类型
SAP Spartacus b2b table,通过listService的table type字段来控制要加载的数据类型
78 0
SAP Spartacus b2b table,通过listService的table type字段来控制要加载的数据类型
两种方法动态获得ABAP类的class attribute的值
两种方法动态获得ABAP类的class attribute的值
184 0
如何使用BOL接口set_property修改SAP CRM BO实例的某个属性
如何使用BOL接口set_property修改SAP CRM BO实例的某个属性
124 0