跟使用其他ORM框架一样,我们生成一个实体类与数据库表对应。
public class Person:Super
{
private int id;
public int ID
{
get
{
return this.id;
}
set
{
this.id=value;
}
}
}
我们再生成一个XML映射文件
<?xml version="1.0" encoding="utf-8" ?>
<map>
<class name="Person">
<attribute name="ID"/>
</class>
</map>
后面会讲为什么需要这两个文件,先别急。现在我们来做数据插入操作。
static void Main(string[] args)
{
Person s=new Person();
s.ID=500;
s.save();
}
这样,数据就插入数据库了。Save哪里来的?Person继承了Super,Save是从Orm框架里来的.Super类在Super.dll里,我们现在使用它是引用它,根本没它的源代码。当我们调用Save方法,Save帮我们做了几件事情。
1、获得Person对象在数据库中的表名
2、获得ID字段名
3、获得ID被赋予的值是多少
4、然后生产Insert into 表名 values(id属性的值) 插入数据库
Super.dll是我N年前写的,我那时怎么知道,你的表名,字段,你赋予的值是多少,我怎么帮你生成SQL啊?
我写Super.dll时候,上面需要的4个东西,我都没有。那怎么办呢?
好莱坞不是电影里:“你不来找我,我就来找你”。呵呵
我无法知道,所以你写代码时候,你主动告诉我。所以就是你为什么要写实体类和XML映射文件的原因。
1.xml是你把你的数据表名和字段名写在里面。
2.实体类,你等下你对属性赋值后,我在N年前就在Super类里读取你的Xml里的字段,然后对实体类反射获得你的属性的值。
这样我能在Super类里得到上面需要的 表名 字段名 和你 实体对象的属性值。那么我是不是可以拼凑sql执行了啊。
下面我们来看Super类的代码。
public class Super
{
public static string GetClassName(Type classType)//获得对象的type为反射做准备
{
string name=classType.ToString();
return name.Substring(name.LastIndexOf('.')+1);
}
public virtual string GetClassName()
{
string name=this.ToString();
return name.Substring(name.LastIndexOf('.')+1);
}
internal object GetAttributeValue(string name))//根据字段名,反射调用属性get方法,获得属性的值
{
Type attributeType=this.GetType();
object rObject=null;
try
{
rObject=attributeType.InvokeMember(name,BindingFlags.GetProperty,null,this,null);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
return rObject;
}
internal void SetAttributeValue(string name,object objValue)//根据字段名,反射调用属性set方法
{
Type attributeType=this.GetType();
object[] objectsValue=new object[1];
objectsValue[0]=objValue;
try
{
attributeType.InvokeMember(name,BindingFlags.SetProperty,null,this,objectsValue);
}
catch
{
}
}
public string getAttributeNameByXml()//通过读取XML获得表名,字段名,我这里写死了,你可以在Super里写个属性,要用户在调用Save前,把xml地址赋值给Super
{
XmlDocument oxmlDocument=new XmlDocument();
oxmlDocument.Load(@"C:\Documents and Settings\zhujian\Desktop\ParentCallSub\ParentCallSub\objMap.xml");
XmlNodeReader rd=new XmlNodeReader(oxmlDocument);
while(rd.Read())
{
if(rd.NodeType!=XmlNodeType.Element) continue;
if(rd.Name.ToLower()=="attribute")
{
return rd.GetAttribute("name").ToString();
}
}
return null;
}
public void save()//我模拟的数据保存方法,为了Demo简单,我只做个打印
{
object obj = GetAttributeValue(getAttributeNameByAttribute());
Console.WriteLine(obj.ToString());
}
}
ORM模拟完毕了。呵呵,是不是很简单啊。
上面是通过xml方式告诉Super 框架,字段表名。
还有通过attribute自定义元属性方式,在代码的属性和类名上直接配置。这样就省去了XML文件。现在JAVA也有这东西了,以前是C#自豪的地方。ActiveRecord、Linqtosql等都支持元属性标记的。
自定义attribute,来标记字段。
[AttributeUsage(AttributeTargets.Property, Inherited = true, AllowMultiple = true)]
public class SelfField:Attribute
{
private string column;
public SelfField(string column)
{
this.column=column;
}
public string Column
{
get
{
return this.column;
}
}
}
现在来改下Super类,让它支持attribute标记。
public class Super
{
public static string GetClassName(Type classType)
{
string name=classType.ToString();
return name.Substring(name.LastIndexOf('.')+1);
}
public virtual string GetClassName()
{
string name=this.ToString();
return name.Substring(name.LastIndexOf('.')+1);
}
internal object GetAttributeValue(string name)
{
Type attributeType=this.GetType();
object rObject=null;
try
{
rObject=attributeType.InvokeMember(name,BindingFlags.GetProperty,null,this,null);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
return rObject;
}
internal void SetAttributeValue(string name,object objValue)
{
Type attributeType=this.GetType();
object[] objectsValue=new object[1];
objectsValue[0]=objValue;
try
{
attributeType.InvokeMember(name,BindingFlags.SetProperty,null,this,objectsValue);
}
catch
{
}
}
public string getAttributeNameByAttribute()//这里就是改动的,现在这里是通过反射,读取attribute属性获得表名和字段的。
{
Type t=this.GetType();
foreach(PropertyInfo pInfo in t.GetProperties(BindingFlags.Public|BindingFlags.Instance))
{
SelfField[] fieldArr=(SelfField[])pInfo.GetCustomAttributes(typeof(SelfField),true);
SelfField field=fieldArr.Length>0?fieldArr[0]:null;
if(field!=null)
{
return field.Column;
}
}
return null;
}
public void save()
{
object obj = GetAttributeValue(getAttributeNameByAttribute());
Console.WriteLine(obj.ToString());
}
}
上面是改进后的框架代码,我们现在来使用这个框架。
同样,实体类
public class Bsub:Super

{
private int id;

[SelfField("ID")]//这里比上次多了个标记了。呵呵
public int ID

{
get

{
return this.id;
}
set

{
this.id=value;
}
}
}
接下来,Main函数。
static void Main(string[] args)
{
Bsub s=new Bsub();
s.ID=800;
s.save();
}
大功告成!写的途中IE挂了一次,这是写第二遍了。希望这篇文章没有浪费你宝贵的时间。别扔鸡蛋啊,石头什么的。
作者:朱剑
2008年5月9号
纯属技术交流,转载请保留文章完整,标明出处。