理解C# 4 dynamic(3) – DynamicObject的使用


上篇文章"理解C# 4 dynamic(2) – ExpandoObject的使用" 了解了ExpandoObject的基本使用。

但ExpandoObject的問題就是它是一個萬金油,什么都可以做,但是又都不專注。

使用DynamicObject正好可以解決這個問題。這篇文章介紹DynamicJson是如何繼承DynamicObject,包裝一個用來處理Json的動態類型。

 

閱讀目錄:

一、JS可以靈活處理Json字符串

二、DynamicObject分析

三、DynamicJson代碼

四、總結

一,JS可以靈活處理Json字符串

看下面的代碼,

var jsonString='{"foo":"json", "bar":100, "nest":{ "foobar":true }}';
var jsonObj = JSON.parse(jsonString);
//接着就能方便的使用
jsonObj.foo
jsonObj.nest.foobar 

代碼中的jsonObj是動態類型,在.net中,我們也可以反序列化Json,但都需要指定反序列化后的對象類型。

比如使用Json.Net

Newtonsoft.Json.JsonConvert.DeserializeObject(json, typeof(employee))

有沒有辦法和js一樣,反序列化一個dynamic類型來方便的訪問Json數據?

下面先來看看DynamicObject如何使用,然后使用DynamicObject來實現我們的想法。

 

二,DynamicObject分析

DynamicObject有個構造函數,但是protected, 也就是我們沒有辦法直接實例化來使用它。只能是通過繼承來構造DynamicObject的對象。

 

同時DynamicObject中很很多標記為Virtual的方法,比如:

public virtual bool TryGetMember(GetMemberBinder binder, out object result);

public virtual bool TrySetMember(SetMemberBinder binder, object value);

當我們寫個類繼承DynamicObject, 這個動態類型類的對象,所具有的特性,就是通過重寫這些virtual方法體現出來的。

 

假設SampleObject 是繼承DynamicObject的類,那么

如果我們重寫了TryGetMember, 在調用 int number = sampleObject.Number.時,就會調用TryGetMemeber方法來得到返回值。

如果我們重寫了TrySetMember,在調用sampleObject.Number = number 時使用,就會調用TrySetMember方法。

 

了解了DynamicObject, 我們的路線就更加清晰了:

我們要寫一個類DynamicJson,繼承自DynamicObject

DynamicJson有靜態Parse方法,接受一個Json的字符串,返回DynamicJson的對象。

DynamicJson重寫TryGetMember方法,這樣當訪問屬性的時候,我們處理,返回正確的值。

三,DynamicJson代碼

DynamicJson正是這個思路實現的,下面來分析一下DynamicJson中一些關鍵代碼

Parse靜態方法

這段代碼非常容易理解,這里將json以xml方式處理,屬性變成了xml中的element處理

public static dynamic Parse(string json)
{
    using (var reader = JsonReaderWriterFactory.CreateJsonReader(Encoding.Unicode.GetBytes(json), XmlDictionaryReaderQuotas.Max))
    {
        return ToValue(XElement.Load(reader));
    }
}

ToValue方法

To value方法根據json反序列化后的xml信息,獲取element的type屬性,然后根據屬性分別處理。

如果是非數組和object類型,就直接返回。

如果是,就返回DynamicJson對象,這樣當我們使用對象的屬性,就會調用TryGetMember方法

private static dynamic ToValue(XElement element)
{
     var type = (JsonType)Enum.Parse(typeof(JsonType), element.Attribute("type").Value);
     switch (type)
     {
         case JsonType.boolean:
             return (bool)element;
         case JsonType.number:
             return (double)element;
         case JsonType.@string:
             return (string)element;
         case JsonType.@object:
         case JsonType.array:
             return new DynamicJson(element, type);
         case JsonType.@null:
         default:
             return null;
    }
}

TryGetMember方法

下面是重寫的TryGetMember方法

public override bool TryGetMember(GetMemberBinder binder, out object result)
{

    //根據訪問的屬性,在序列化的xml結構中尋找子element.
    var element = xml.Element(binder.Name);

    if (element == null)
    {
         result = null;
         return false;
    }

     result = ToValue(element);//如果存在該element, 就繼續調用ToValue, 如果是普通類型,就能夠返回具體的內容,如果是數組或object,就在返回一個DynamicJson對象。
     return true;
}

四,總結

DynamicJson的代碼實現的功能很多,詳細的DynamicJson的代碼,可以通過Nuget獲取。

通過繼承DynamicObject類,實現了非常多的功能類,

有針對Json的DynamicJson,還有針對xml的DynamicXml

使用它們,減少了不必要的類型定義,增加了程序代碼的靈活性。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM