C# 如何動態生成dynamic物件-ExpandoObject

  • 9766
  • 0
  • C#
  • 2020-07-27

一直以來都知道Dapper在做存取資料庫方面非常的簡單,只需要給予該SQL語法以及回傳的Model型別,就可以將對應的資料回傳並且轉換成List。

而其中Dapper還有一個最厲害的地方就是:不用預先宣告強型別,查詢資料表後就可以直接傳回 dynamic 的List。

例如:var list = cn.Query("SELECT Name,Class FROM Student").ToList();

該語法將傳回 List<dynamic>,因此不需要特別建立Model也可以將該資料回傳並作使用。

因此開始思考,如何透過dynamic動態生成物件?

今天就來介紹如何使用ExpandoObject動態建立欄位,並將資料回傳成 List<dynamic>吧!

ExpandoObject是在.Net Framework 4之後出現的一個類別 ,可以幫助我們為物件動態的加入或移除屬性成員。

其用法為:

dynamic data = new ExpandoObject();
data.Name = "Leo";
data.Sex= "Male";

我們需要搭配dynamic才能夠存取我們指定的Name,Sex欄位。

但是僅僅這樣寫,雖然可以自動幫我們建立Namx,Sex欄位,並給予值。但若是在欄位名稱未知的情況下想要動態建立Model,可就沒辦法了。

如上面所說,若需要將撈出來的SQL資料,根據其欄位建立Model並賦予值,那肯定無法做到。

但值得一提的是,由於ExpandoObject本身就實作了IDictionary<string, object>,因此若是有必要我們也可以直接把它轉型成IDictionary<string, object>來操作,讓該物件擁有Add以及Remove的方法,為物件動態的加入或移除屬性成員。

因此撰寫上我們會改為這樣的寫法:

var MyDynamic = new ExpandoObject() as IDictionary<string, Object>;
MyDynamic.Add("Name", "leo");
MyDynamic.Add("Sex", "Male");

透過這樣的方式,將我們的屬性利用字串的方式Add至MyDynamic物件中,這樣我們就能存取Name以及Sex的值了。

因此若想像Dapper一樣回傳成List<dynamic>的集合資料的話,最終的版本可以寫成這樣:

// 本範例使用SqlDataReader做資料庫存取

    List<dynamic> list = new List<dynamic>();
    SqlCommand command = new SqlCommand(sql, connection);
    SqlDataReader reader = command.ExecuteReader();
    while (reader.Read())
    {
      IDictionary<String, Object> MyDynamic = new ExpandoObject() as IDictionary<string, Object>;

      for (int i = 0; i < reader.FieldCount;i++) // 透過FieldCount 取得該列資料中的所有欄位數目
      {
        MyDynamic.Add(reader.GetName(i), reader[i]); //動態將SQL存取到的欄位以及Value 放入MyDynamic中
      }
       list.Add(MyDynamic);
    }

透過這樣的方式,我們就可以像Dapper一樣,不需要建立Model類別,也能輕鬆的將資料存取回來,並轉換為List做後續操作。

另外,仔細追查Dapper的原始碼,我們也可以發現到,Dapper之所以能做到不需要指定Model型別,也能回傳dynamic的List的原因,也是透過實作了IDictionary<string, object>

因此在dapper中,外表看似是dynamic其實骨子裡是DapperRow的型別。

以上文章敘述如有錯誤及觀念不正確,請不吝嗇指教:)

有任何家教、案子 或技術相關問題 請都歡迎聯繫我

http://www.zhenghui.idv.tw/