背景: 在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,如果外面對不存在的屬性復制那麼將會報錯.