熟悉ruby on rails的开发员都知道,在ruby中,有一个很重要的特性,就是能够实现元编程,特别是在用于开发Web应用的rails框架中,用的特别多。在rails中,要创建一个动态方法并与数据库表字段相关联,主要的的步骤大概有这些:
1、首先配置好数据库的连接。
2、创建一个ActiveRecord模型,这个模型与数据库的表名称有一定的关系(具体的可以参考相关rails文档)
3、创建的一个ActiveRecord是继承于Base类的,其中Base类中封装了基本的CRUD操作
3、然后在程序运行时,动态关联到表的字段,或者执行数据可的CRUD操作。
比如有一个作者表author,包含有字段id,first_name,last_name。然后用rails工具生成一个与之关联的Module类Author,它是一个空类:
class Author < ActiveRecord::Base
end
然而,在实际操作中,我们却可以这样操作它:
@author = Author.find(id)
@name = @author.first_name
@author.destory
这些在静态语言C#中是不可能做得到的。在C#的动态方法没有出现之前,通常为了实现实体与数据库的表映射,都是先创建一个固定的实体类,实体类的属性通过Attribute映射到表的字段,一般都是像下面的代码所示:
[TableMap("overtimeinfo","id")]
public class OverTimeEntity
{
[ColumnMap("id",DbType.Int32)]
public int GUID{get;set;}
[ColumnMap("applyUser",DbType.String,"")]
public string UserName{get;set;}
[ColumnMap("applyuserid",DbType.Int32)]
public int UserId{get;set;}
[ColumnMap("FormNo",DbType.String,"")]
public string FormNo{get;set;}
}
以上的C#代码能这样写还得靠C# 3.0提供了属性的自动实现,在这之前,都是需要要有相应的私有字段的,所以那时的办法是事先定义好一个与表结构相同的抽象类,抽象类定义好属性,然后利用CodeDom根据抽象类动态编译一个抽象类的实现类,下面的代码为抽象类:
[TableMap("overtimeinfo","id")]
public abstract class OverTimeEntity
{
[ColumnMap("id",DbType.Int32)]
public abstract int GUID{get;set;}
[ColumnMap("applyUser",DbType.String,"")]
public abstract string UserName{get;set;}
[ColumnMap("applyuserid",DbType.Int32)]
public abstract int UserId{get;set;}
[ColumnMap("FormNo",DbType.String,"")]
public abstract string FormNo{get;set;}
[ColumnMap("flowid",DbType.String,"")]
public abstract string Flowid{get;set;}
}
在C#中,通过以上的途径来实现与数据库的ORM映射,可以想象那时的编写一个实体类那么的难,特别是存在几十、甚至上百个表的时候,尽管可以自己编写一个代码工具。
幸运的是,在.NET 4.0中,C#已经提过了与动态语言类似的动态方法调用,一切都变得那么的容易了,可以终于从代码中解脱出来,专注于业务实现方面。下面的例子简单的演示了C#是如何实现动态方法调用的,只要是用到了关键字dynamic :
class DynamicTest
{
public void PrintText()
{
Console.WriteLine("call dynamic method....");
}
}
上面定义了一个类,然后我们就可以这样创建一个实例:
static void Main(string[] args)
{
dynamic test = new DynamicTest();
test.PrintText();
Console.ReadKey(true);
}
虽然这样看起来与DynamicTest test = new DynamicTest();创建一个实例后调用PrintText没有任何的区别,但是别忘记了,动态方法最主要的是它在编译时是不检测,而在运行时检测的,所以这中间可以让我们做很多可以改变原有类的事情。
现在我就通过一个示例来演示下如何利用C#的动态方法来实现与数据库表的映射。
一、创建基类以及具体的实体类
首先,创建一个所有Module都要集成的基类BaseActiveRecord,里面封装了CRUD的数据库操作,还有一个获取表名和主键名的属性,BaseActiveRecord类的代码如下:
public abstract class Base