標籤:
背景: 在Coding中有時候會遇到一些需要解析的資料,可是資料的欄位數量和名稱未統一,我們沒法定義實體類來對應。那麼我們就會想到通過C#的dynamic動態類來實現,如果大家注意的話一些ORM架構裡面貌似都有用到dynamic來實現一部分功能。
一.Dynamic的基本應用
1.1 通過.PropertyName來添加屬性,和JavaScript的對象差不多.不過對於我們所要解析的資料,我們事先也許根本不知道屬性名稱,所以用這種方法意義不大.
dynamic myObj = new ExpandoObject();myObj.Name = "Frank";Console.WriteLine(myObj.Name);
二.Dynamic自訂屬性名稱.
2.1: 繼承DynamicObject,裡面提供了各種方法,重寫後可以實現屬性的添加.
public sealed class MyExtendsObject : DynamicObject { private readonly Dictionary<string, object> _properties; public MyExtendsObject(Dictionary<string, object> properties) { _properties = properties; } public override IEnumerable<string> GetDynamicMemberNames() { return _properties.Keys; } public override bool TryGetMember(GetMemberBinder binder, out object result) { if (_properties.ContainsKey(binder.Name)) { result = _properties[binder.Name]; return true; } else { result = null; return false; } } public override bool TrySetMember(SetMemberBinder binder, object value) { if (_properties.ContainsKey(binder.Name)) { _properties[binder.Name] = value; return true; } else { return false; } } }
2.2 通過字典來添加屬性和賦值
public static void Main(string[] args) { dynamic myObj = new ExpandoObject(); Dictionary<string, object> dic = new Dictionary<string, object>() { {"Name","Frank"}, {"Age",23} }; myObj = new MyExtendsObject(dic); Console.WriteLine(myObj.Age); //23 }
三.Dynamic解析XML.
3.1 定義xml檔案:
<?xml version="1.0" encoding="utf-8" ?><Person> <Name>Frank</Name> <Age>23</Age> <Address>TianFu SoftWarePark</Address></Person>
3.2 繼承DynamicObject
public sealed class MyExtensXMLObj : DynamicObject { private readonly XElement node; public MyExtensXMLObj(XElement node) { this.node = node; } public override bool TrySetMember(SetMemberBinder binder, object value) { var elements = node.Elements().ToList(); var currentElement = elements.FirstOrDefault(x => x.Name == binder.Name); if (currentElement != null) { currentElement.Value = value as string; return true; } else { return false; } } public override bool TryGetMember(GetMemberBinder binder, out object result) { var elements = node.Elements().ToList(); var currentElement = elements.FirstOrDefault(x => x.Name == binder.Name); if (currentElement != null) { result = currentElement.Value; return true; } else { result = null; return false; } } }
3.3 結果輸出:
public static void Main(string[] args) { XElement root = XElement.Load(@"Test.xml"); dynamic personList = new MyExtensXMLObj(root); Console.WriteLine(personList.Name); // Frank }
四. 繼承規則.
1. 子類裡麵包含一個私人變數,用於儲存資料. 這暫且叫做Data;
2.TryGetMember(GetMemberBinder binder, out object result) 方法實現對資料的擷取. binder.Name就是需要擷取的屬性的名稱,result 是擷取的屬性值. 通過binder.Name在Data中擷取到對應的屬性值,傳出到外面.(注意到了吧result是out參數)
3.TrySetMember(SetMemberBinder binder, object value) 對存在的屬性進行賦值. 上面的Set方法中,我都判斷了binder.Name在data裡面是否存在。如果不存在就無法賦值。返回false,如果外面對不存在的屬性複製那麼將會報錯.
C#筆記---動態類(Dynamic)應用