反射以及Attribute在ORM中的應用

GPS平臺、網站建設、軟件開發、系統運維,找森大網絡科技!
http://cnsendnet.taobao.com
來自森大科技官方博客
http://www.cnsendblog.com/index.php/?p=488

反射以及Attribute在ORM中的應用
一、 反射
什麼是反射?
簡單點吧,反射就是在運行時動態獲取對象信息的方法,比如運行時知道對象有哪些屬性,方法,委託等等等等。
反射有什麼用呢?
反射不但讓你在運行是獲取對象的信息,還提供運行時動態調用對象方法以及動態設置、獲取屬性等的能力。
反射在ORM中有什麼用呢?
我這裏所討論的ORM實現是通過自定義Attribute的方式進行映射規則的描述的。但是我們並不知道具體哪個對象需要對應哪個表,並且這些對象是獨立於我們的ORM框架的,所以我們只能通過自定義Attribute來定義映射規則,然後通過反射來動態獲取這些映射規則。
反射的實現:
下面我們就以簡單的獲取對象的屬性值的方式來做討論,假設我們有類Person,其中有3個屬性Name、Age,Sex。我們通過反射的方法來動態獲取Person的對象的這三個屬性的值。

  1. public class Person
  2. {
  3. private string _Name;
  4. private int _Age;
  5. private string _Sex;
  6. public string Name
  7. {
  8. get { return this._Name; }
  9. set { this._Name = value; }
  10. }
  11. public int Age
  12. {
  13. get { return this._Age; }
  14. set { this._Age = value; }
  15. }
  16. public string Sex
  17. {
  18. get { return this._Sex; }
  19. set { this._Sex = value; }
  20. }
  21. }
    測試代碼如下:

  22. static class Program
  23. {
  24. [STAThread]
  25. static void Main()
  26. {
  27. Person person = new Person();
  28. person.Name = "snoopy";
  29. person.Age = 5;
  30. person.Sex = "male";
  31. PropertyInfo[] infos = person.GetType().GetProperties();
  32. Console.WriteLine("打印屬性");
  33. foreach (PropertyInfo info in infos)
  34. {
  35. //獲取屬性並打印
  36. Console.WriteLine(info.Name + ":" + info.GetValue(person, null));
  37. }
  38. Console.WriteLine("設置Person.Name = Hellokitty");
  39. //設置屬性,設置Name屬性
  40. foreach (PropertyInfo info in infos)
  41. {
  42. if (info.Name == "Name")
  43. {
  44. info.SetValue(person, "Hellokitty", null);
  45. }
  46. }
  47. Console.WriteLine("打印屬性");
  48. foreach (PropertyInfo info in infos)
  49. {
  50. //獲取屬性並打印
  51. Console.WriteLine(info.Name + ":" + info.GetValue(person, null));
  52. }
  53. Console.Read();
  54. }
  55. }
    反射以及Attribute在ORM中的應用
    上面演示了通過反射的方法來動態獲取和設置對象屬性的方法。但是這和ORM以及Attribute有什麼關係呢?這個是我們接下來的這個部分的內容。

二、Attribute的使用:
Attribute中文翻譯雖然也號稱“屬性”,但是她和對象的屬性(Property)其實是完全不同的兩概念。她是在運行時對對象或者對象屬性、方法、委託等等進行描述的類,用於在運行時描述你的代碼或者在運行時影響你的程序的行爲。
其實我們在c#的編程中經常看到Attribute,只不過我們沒有注意罷了。比如Main函數前的“[STAThread]”這個其實就是一個Attribute。全程爲[STAThreadAttribute]。另外指定類可序列化的[Serializable]等等。是不是都很熟悉啊?只不過平時估計沒有用到,所以沒有注意罷了。
既然Attribute是類,那麼她的定義方法和類就沒有兩樣了,唯一的不同就是自定義Attribute類必須繼承於System.Attribute。
下面我們來簡單定義一個描述數據庫字段信息的Attribute,在此類中我們採用更省略的方式,僅僅提供“字段名”,“字段類型”:

  1. public class DataFieldAttribute : Attribute
  2. {
  3. private string _FieldName;
  4. private string _FieldType;
  5. public DataFieldAttribute(string fieldname, string fieldtype)
  6. {
  7. this._FieldName = fieldname;
  8. this._FieldType = fieldtype;
  9. }
  10. public string FieldName
  11. {
  12. get { return this._FieldName; }
  13. set { this._FieldName = value; }
  14. }
  15. public string FieldType
  16. {
  17. get { return this._FieldType; }
  18. set { this._FieldType = value; }
  19. }
  20. }
    好,我們有了自己的描述數據庫字段的Attribute,那麼我們現在將其應用到實際的類中。我們還是繼續上面的Person類,使用方法如下:

  21. public class Person
  22. {
  23. private string _Name;
  24. private int _Age;
  25. private string _Sex;
  26. [DataFieldAttribute("name", "nvarchar")]
  27. public string Name
  28. {
  29. get { return this._Name; }
  30. set { this._Name = value; }
  31. }
  32. [DataFieldAttribute("age", "int")]
  33. public int Age
  34. {
  35. get { return this._Age; }
  36. set { this._Age = value; }
  37. }
  38. [DataFieldAttribute("sex", "nvarchar")]
  39. public string Sex
  40. {
  41. get { return this._Sex; }
  42. set { this._Sex = value; }
  43. }
  44. }
    通過自定義Attribute,我們定義了類屬性和數據庫字段的一一對應關係,我們對Person類的Name、Age、Sex屬性都加上了Attribute的描述,指定了他們對應的字段名以及類型,其中Person.Name對應於字段name,字段類型Nvarchar...。
    三、反射和Attribute的聯合使用。
    從上面的描述中,我們瞭解了反射,瞭解了Attribute,瞭解了ORM映射規則的定義。但是剛接觸的朋友估計還是迷惑,我們怎麼動態獲取這些映射規則呢?聽灑家慢慢道來。
    這就需要使用反射了:
    下面的例子,我們由於對Person中的Name,Age以及SEX都增加了DataFieldAttribute的描述,這其實就是增加了O(對象)/R(關係數據庫)的映射規則,下面我們就通過反射的方法來動態獲取此映射規則:
  45. static class Program
  46. {
  47. [STAThread]
  48. static void Main()
  49. {
  50. Person person = new Person();
  51. person.Name = "snoopy";
  52. person.Age = 5;
  53. person.Sex = "male";
  54. PropertyInfo[] infos = person.GetType().GetProperties();
  55. object[] objDataFieldAttribute = null;
  56. foreach (PropertyInfo info in infos)
  57. {
  58. objDataFieldAttribute = info.GetCustomAttributes(typeof(DataFieldAttribute), false);
  59. if (objDataFieldAttribute != null)
  60. {
  61. Console.WriteLine(info.Name + "->數據庫字段:" + ((DataFieldAttribute)objDataFieldAttribute[0]).FieldName);
  62. }
  63. }
  64. }
  65. }
    反射以及Attribute在ORM中的應用
    哈哈,你是不是很想動手了啊?當然瞭如果你到了這一步就開始動手的話,那我就很高興了,說明我的描述還算清楚(注:對於已經知道的大牛們此話無效)。也說明你很有動手的能力。因爲接下來的工作就是怎樣根據這種方法動態地從對象中獲取映射規則,動態構造Insert,Update,Delete等語句。
    四、本章總結
    本章中我比較詳細地介紹了反射,自定義Attribute的概念和應用,並且介紹了怎樣在運行時動態獲取O/R Mapping的映射規則等。當然我這裏的代碼僅僅是舉例,而要真正實現一個ORM,我們還需要考慮的很多,比如:
    1、Person對應於哪張數據庫表?
    2、Person中的PK和FK(如果有的話)怎麼表示?
    ......
    這些問題將在我的下一篇中進行講解。

GPS平臺、網站建設、軟件開發、系統運維,找森大網絡科技!
http://cnsendnet.taobao.com
來自森大科技官方博客
http://www.cnsendblog.com/index.php/?p=488

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章