asp.net c# 輕量ORM架構開發之反射與動態編譯

來源:互聯網
上載者:User

對象關係映射,靠純手打,是個超級繁瑣又類的苦力活,即便它能給你再高的運行效率,但是也會損失開發效率。

c#在netframework中其實已經提供了ORM架構了,叫做entity framework,這個架構其實已經做的蠻好的了,但是架構實在是太重,重到寫出來的代碼在配置不那麼好的電腦上跑起來都卡頓。

因此我們決定自己寫這麼一個架構,一來重在輕量;二來,就是想探探路,看看ORM架構到底是怎麼做出來的。

當然,讓我自己憑空造樓是做不到的,但是我們可以借鑒,尤其是在互連網這麼發達的時代,去github看看別的的開原始碼就OK了。


一、反射。

首先我們要解決的就是當從資料庫中取出值來了之後,怎麼直接賦值給相應的對象的屬性的問題,我們記得,傳統的做法就是

dt.Rows[i][“ID”]

這麼一個一個欄位去寫,碰到欄位比較多的表,那就會打半天了。

反射,就是要獲得該類的變數的名稱,然後賦值給該變數:

 代碼如下 複製代碼

public List<T> ExecSelect<T>(string sqlCmd) where T : new()
        {
            List<T> list = new List<T>();
            DataTable dt = Select(sqlCmd);

            if (dt.Rows.Count == 0)
            {
                return list;
            }

            PropertyInfo[] properties = ReflectionHelper.GetProperties(new T().GetType());

            for (int i=0;i<dt.Rows.Count;i++)
            {
                T entity = new T();
                foreach (PropertyInfo property in properties)
                {
                    String name = property.Name;
                    ReflectionHelper.SetPropertyValue(entity, property, dt.Rows[i][name]);
                }
                list.Add(entity);
            }

            return list;

        }

以上的T就是一種泛型,至於泛型是什麼,自行百度。

GetProperties函數即是泛型用於擷取類的變數的方法,它有一些參數,包括擷取變數為public修飾等等參數:

 代碼如下 複製代碼
 public static PropertyInfo[] GetProperties(Type type)
        {
            return type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
        }

二、Value.

既然我們已經通過GetProperties擷取了該類的屬性,那麼通過SetValue直接給其賦值就好了,問題是,如果我們從資料庫中取出來的值和它不匹配呢,因此我們需要轉化Value類型。

 代碼如下 複製代碼

if (Convert.IsDBNull(value) || (value == null))
            {
                return null;
            }

            string typeName = type.FullName.ToString();
            System.Console.WriteLine(typeName);

            if (type == typeof(System.Nullable<UInt16>))
            {
                value = Convert.ToUInt16(value);
            }
            else if (type == typeof(System.Nullable<UInt32>))
            {
                value = Convert.ToUInt32(value);
            }
            else if (type == typeof(System.Nullable<UInt64>))
            {
                value = Convert.ToUInt64(value);
            }
            else if (type == typeof(System.Nullable<Int32>))
            {
                value = Convert.ToInt32(value);
            }
            else if (type == typeof(System.Nullable<Int64>))
            {
                value = Convert.ToInt64(value);
            }

            switch (typeName)
            {
                case "System.String":
                    if (!isNullOrEmpty(value))
                        value = value.ToString();
                    break;
                case "System.Boolean":
                    if (!isNullOrEmpty(value))
                        value = Convert.ToBoolean(value);
                    break;
                case "System.Int16":
                    if (!isNullOrEmpty(value))
                        value = Convert.ToInt16(value);
                    break;
                case "System.Int32":
                    if (!isNullOrEmpty(value))
                        value = Convert.ToInt32(value);
                    break;
                case "System.Int64":
                    if (!isNullOrEmpty(value))
                        value = Convert.ToInt64(value);
                    break;
                case "System.Double":
                    if (!isNullOrEmpty(value))
                        value = Convert.ToDouble(value);
                    break;
                case "System.Float":
                    if (!isNullOrEmpty(value))
                        value = Convert.ToDouble(value);
                    break;
                case "System.Single":
                    if (!isNullOrEmpty(value))
                        value = Convert.ToDouble(value);
                    break;
                case "System.Decimal":
                    if (!isNullOrEmpty(value))
                        value = Convert.ToDecimal(value);
                    break;
                case "System.DateTime":
                    if (!isNullOrEmpty(value))
                        value = Convert.ToDateTime(value);
                    break;
            }

            return value;
        }

三、反射與動態編譯。

Reflection真的是個好東西,但是net4.0後會有一個更好的東西:dynamic,要知道反射其實是很費效率的,但是動態編譯就會快的多,如果你不理解dynamic,那麼以下的例子就會告訴你這兩者的區別:

public void test()
        {
            SomeClass c = new SomeClass();

            PropertyInfo property = c.GetType().GetProperties()[0];

            StartTest("begin reflection.");

            for (int i = 0; i < 1000000; i++)
            {
                property.SetValue(c, i, null);
            }

            EndTest("end reflection");

            IDynamicPropertyInfo dproperty = new DynamicType(c.GetType()).GetProperties()[0];

            StartTest("begin dynamic.");

            for (int i = 0; i < 1000000; i++)
            {
                dproperty.SetValue(c, i, null);
            }

            EndTest("end dynamic");
        }

那麼這兩者的時間差呢:

—— Test started: Assembly: Pixysoft.Framework.Reflection.dll ——

begin reflection.
end reflection
00:00:09.0625000

begin dynamic.
end dynamic
00:00:00.0468750

差別就太遠了,所以如果你覺得因為反射你的程式變慢了,不如試試動態編譯。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.