程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> 關於C# >> C#基礎系列:實現自己的ORM(反射以及Attribute在ORM中的應用)

C#基礎系列:實現自己的ORM(反射以及Attribute在ORM中的應用)

編輯:關於C#

一、 反射

什麼是反射?

簡單點吧,反射就是在運行時動態獲 取對象信息的方法,比如運行時知道對象有哪些屬性,方法,委托等等等等。

反射有什麼用呢?

反射不但讓你在運行是獲取對象的信息,還提 供運行時動態調用對象方法以及動態設置、獲取屬性等的能力。

反射在 ORM中有什麼用呢?

我這裡所討論的ORM實現是通過自定義Attribute的方 式進行映射規則的描述的。但是我們並不知道具體哪個對象需要對應哪個表,並 且這些對象是獨立於我們的ORM框架的,所以我們只能通過自定義Attribute來定 義映射規則,然後通過反射來動態獲取這些映射規則。

反射的實現:

下面我們就以簡單的獲取對象的屬性值的方式來做討論,假設我們有類 Person,其中有3個屬性Name、Age,Sex。我們通過反射的方法來動態獲取 Person的對象的這三個屬性的值。

public class Person
{
  private string _Name;
  private int _Age;
   private string _Sex;
  public string Name
  {
     get { return this._Name; }
    set { this._Name = value; }
  }
  public int Age
  {
    get { return this._Age; }
    set { this._Age = value; }
   }
  public string Sex
  {
    get { return this._Sex; }
    set { this._Sex = value; }
  }
}

測試代碼如下:

static class Program
{
  [STAThread]
  static void Main()
  {
    Person person = new Person();
    person.Name = "snoopy";
    person.Age = 5;
     person.Sex = "male";
    PropertyInfo[] infos = person.GetType().GetProperties();
    Console.WriteLine ("打印屬性");
    foreach (PropertyInfo info in infos)
    {
      //獲取屬性並打印
       Console.WriteLine(info.Name + ":" + info.GetValue (person, null));
    }
    Console.WriteLine(" 設置Person.Name = Hellokitty");
    //設置屬性,設置Name 屬性
    foreach (PropertyInfo info in infos)
     {
      if (info.Name == "Name")
       {
        info.SetValue(person, "Hellokitty", null);
      }
    }
     Console.WriteLine("打印屬性");
    foreach (PropertyInfo info in infos)
    {
      //獲取屬 性並打印
      Console.WriteLine(info.Name + ":" + info.GetValue(person, null));
    }
     Console.Read();
  }
}

上面演示了通過反射的方法來動態獲取和設置對象屬性的方法。但是 這和ORM以及Attribute有什麼關系呢?這個是我們接下來的這個部分的內容。

上面演示了通過反射的方法來動態獲取和設置對象屬性的方法。但是這 和ORM以及Attribute有什麼關系呢?這個是我們接下來的這個部分的內容。

二、Attribute的使用:

Attribute中文翻譯雖然也號稱“ 屬性”,但是她和對象的屬性(Property)其實是完全不同的兩概念。她 是在運行時對對象或者對象屬性、方法、委托等等進行描述的類,用於在運行時 描述你的代碼或者在運行時影響你的程序的行為。

其實我們在c#的編程 中經常看到Attribute,只不過我們沒有注意罷了。比如Main函數前的“ [STAThread]”這個其實就是一個Attribute。全程為 [STAThreadAttribute]。另外指定類可序列化的[Serializable]等等。是不是都 很熟悉啊?只不過平時估計沒有用到,所以沒有注意罷了。

既然 Attribute是類,那麼她的定義方法和類就沒有兩樣了,唯一的不同就是自定義 Attribute類必須繼承於System.Attribute。

下面我們來簡單定義一個描 述數據庫字段信息的Attribute,在此類中我們采用更省略的方式,僅僅提供 “字段名”,“字段類型”:

public class DataFieldAttribute : Attribute
{
  private string _FieldName;
  private string _FieldType;
  public DataFieldAttribute(string fieldname, string fieldtype)
  {
    this._FieldName = fieldname;
    this._FieldType = fieldtype;
  }
  public string FieldName
  {
    get { return this._FieldName; }
    set { this._FieldName = value; }
  }
  public string FieldType
  {
    get { return this._FieldType; }
    set { this._FieldType = value; }
  }
}

好,我們有了自己的描述數據庫字段的Attribute,那麼我們現 在將其應用到實際的類中。我們還是繼續上面的Person類,使用方法如下:

public class Person
{
  private string _Name;
  private int _Age;
  private string _Sex;
  [DataFieldAttribute("name", "nvarchar")]
  public string Name
  {
    get { return this._Name; }
    set { this._Name = value; }
  }
  [DataFieldAttribute("age", "int")]
   public int Age
  {
    get { return this._Age; }
    set { this._Age = value; }
  }
   [DataFieldAttribute("sex", "nvarchar")]
   public string Sex
  {
    get { return this._Sex; }
    set { this._Sex = value; }
  }
}

通 過自定義Attribute,我們定義了類屬性和數據庫字段的一一對應關系,我們對 Person類的Name、Age、Sex屬性都加上了Attribute的描述,指定了他們對應的 字段名以及類型,其中Person.Name對應於字段name,字段類型Nvarchar...。

三、反射和Attribute的聯合使用。

從上面的描述中,我們了解 了反射,了解了Attribute,了解了ORM映射規則的定義。但是剛接觸的朋友估計 還是迷惑,我們怎麼動態獲取這些映射規則呢?聽灑家慢慢道來。

這就 需要使用反射了:

下面的例子,我們由於對Person中的Name,Age以及 SEX都增加了DataFieldAttribute的描述,這其實就是增加了O(對象)/R(關系 數據庫)的映射規則,下面我們就通過反射的方法來動態獲取此映射規則:

static class Program
{
  [STAThread]
   static void Main()
  {
    Person person = new Person();
    person.Name = "snoopy";
     person.Age = 5;
    person.Sex = "male";
     PropertyInfo[] infos = person.GetType().GetProperties();
     object[] objDataFieldAttribute = null;
    foreach (PropertyInfo info in infos)
    {
       objDataFieldAttribute = info.GetCustomAttributes(typeof (DataFieldAttribute), false);
      if (objDataFieldAttribute != null)
      {
         Console.WriteLine(info.Name + "->數據庫字段:" + ((DataFieldAttribute)objDataFieldAttribute[0]).FieldName);
       }
    }
  }
}

哈哈,你是不是很想動手了啊?當然了如果你到了這一步就開始動手 的話,那我就很高興了,說明我的描述還算清楚(注:對於已經知道的大牛們此 話無效)。也說明你很有動手的能力。因為接下來的工作就是怎樣根據這種方法 動態地從對象中獲取映射規則,動態構造Insert,Update,Delete等語句。

四、本章總結

本章中我比較詳細地介紹了反射,自定義 Attribute的概念和應用,並且介紹了怎樣在運行時動態獲取O/R Mapping的映射 規則等。當然我這裡的代碼僅僅是舉例,而要真正實現一個ORM,我們還需要考 慮的很多,比如:

1、Person對應於哪張數據庫表?

2、Person中 的PK和FK(如果有的話)怎麼表示?

......

這些問題將在我的下 一篇中進行講解。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved