文章目錄
使用 string 建立 instance 及反序列化 json 為 class
最近的專案在架構拆分時,將可能可以共用的部份獨立設計成開放式的服務,將執行行為也當做輸入參數的一部份,直接交由使用端自行定義。雖然功能開發時遇到不少問題需要逐一的克服,卻可以擁有極大的彈性
今天就針對其中的一小部份語法做個紀錄:如何使用 string 產生 instance 及反序列化 json 為 class
基本設定
有個 Model class 為 User,獨立於各個專案之外,其他專案皆引用 dll 來使用 User
public class User { public Guid _internalId{ get; set; } public string Id { get; set; } public string Name { get; set; } public string Addr { get; set; } public string Phone { get; set; } public int BirthMonth { get; set; } }
輸入端需要傳送 class 的 TypeName
接收端使用 class 的 TypeName 將已轉換為 json string 的 User 進行反序列化
關於 class 的 TypeName
組成
命名空間,加上逗號,後面接著組件的顯示名稱 (
Namespace,AssemblyName
)範例
TestForNuget.User, TestForNuget, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
符號含義
分隔符號 意義 反斜線 () 跳逃字元 逗號 (,) 後面接著組件名稱。 加號 (+) 之前的巢狀的類別。 句號 (.) 代表命名空間識別項。 括號 ([]) 類型名稱後面,表示該類型的陣列
-或-
對於泛型類型,封入泛型型別引數清單
-或-
在型別引數清單中,會封裝至組件限定的類型。取得方式
使用
AssemblyQualifiedName
屬性var typename=typeof(User).AssemblyQualifiedName;
其他方式?
先取得 assembly name
Assembly asm = typeof(User).Assembly; asm.FullName.Dump(); //以下為極簡寫法 //typeof(User).Assembly.FullName.Dump();
取得 class 名稱
User dto = new User(); dto.GetType().FullName.Dump(); //以下為極簡寫法 //typeof(User).FullName.Dump();
將兩者組合
$"{dto.GetType().FullName}, {asm.FullName}".Dump();
結果與直接使用
AssemblyQualifiedName
相同,但實際測試下,如果該 class 在建立 instance 前已被使用過就可以成功建立,但如果從未使用不使用AssemblyQualifiedName
會無法建立 instance
將 string 轉為 class Type
Type dataType = Type.GetType(typename);
這邊的 dataType 如果為 null ,請檢查 typename 是否為合格的 typeName
使用 Type 建立 instance
寫法 一
使用 assembly name 與 type name 來建立 instance,需多一層轉換
//使用 assembly name 與 type name 建立 instance var tempInstance = Activator.CreateInstance(asm.FullName, dto.GetType().FullName); //將封裝的 instance 拆封,並轉為正確 class type var realInstance = Convert.ChangeType(tempInstance.Unwrap(), parameterDataType);
寫法 二
直接使用
AssemblyQualifiedName
來建立 instancevar parameterInstance = Activator.CreateInstance(dataType);
將 json string 反序列化為指定 class Type
JsonConvert.DeserializeObject(jsonstr,dataType)
完整成果程式碼
發送端
void Main() { var typename = typeof(User).AssemblyQualifiedName; User dto = new User() { _internalId = Guid.NewGuid(), Name = "Yowko", Addr = "Taipei", BirthMonth = 7, Id = "A123456789", Phone = "09123456789" }; var jsonstr = JsonConvert.SerializeObject(dto); SendObj(typename,jsonstr); } void SendObj(string typename,string jsonstr) { //web request }
接收端
public IHttpActionResult Post([FromBody]PstData value) { Deserialize(value.typename,value.jsonstr); } void Deserialize(string typename,string jsonstr) { Type dataType = Type.GetType(typename); var obj = JsonConvert.DeserializeObject(jsonstr, dataType); // do something } public class PstData { public string typename { get; set; } public string jsonstr { get; set; } }
心得
就完成的程式碼來看,程式碼數量非常少,但卻花了不少時間才找到正確的方法跟 debug。不得不承認對於 C# 語法基礎還是有很多需要好好努力的地方,透過這種專案實作來嘗試不同寫法,雖然會比較辛苦,但的確是學習的好方式,如同 coding 角度的走出舒適圈 XD
參考資訊
文章作者 Yowko Tsai
上次更新 2021-10-15
授權合約
本部落格 (Yowko's Notes) 所有的文章內容(包含圖片),任何轉載行為,必須通知並獲本部落格作者 (Yowko Tsai) 的同意始得轉載,且轉載皆須註明出處與作者。
Yowko's Notes 由 Yowko Tsai 製作,以創用CC 姓名標示-非商業性-相同方式分享 3.0 台灣 授權條款 釋出。