.Net下一個類型轉換神器


引言

類型轉換經常遇到,最常用的應該是string類型轉換為其它基元類型,常見於http參數類型轉換。Convert靜態類的Convert.ChangeType()方法可以把實現IConvertible接口的類型轉換為其它也實現這個接口的類型,也等同於里面的ToInt32()、ToDecimal()等方法的功能,但不支持轉換到這類型的可空類型,因為Nullable<>類型並沒有實現IConvertible這個接口;此外JavaScriptSerializer.ConvertToType()這個方法相對強大,支持轉換到Nullable<>類型、字符串到枚舉,也支持IDictionary<string,object>類型轉換為對象,居於原因,是為了JavaScriptSerializer在反序列化JSON為動態類型后,能把這些類型進行轉換為常見類型,但JavaScriptSerializer.ConvertToType方法不能擴展。

神器來了

名稱:

今天主角轉換器叫Converter,這是花費我幾天時間才琢磨出來。

點再下載代碼(也要點個贊哦)

功能:

今它支持基礎類型、decimal、guid和枚舉相互轉換以及這些類型的可空類型和數組類型相互轉換,支持字典和DynamicObject轉換為對象以及字典和DynamicObject的數組轉換為對象數組。

擴展性:

可以增加其它類型轉換,或修改某種轉換規則,也就是說轉換器是支持功能部分重寫和功能擴展的,功能移除也支持,比如想干掉DynamicObject類型的轉換也可以。

神器使用方法

1、使用靜態方法,Converter.Cast(object value,Type targetType)或其泛型方法 :Converter.Cast<int?[]>(new[] {null, "2" }

2、實例化來調用,new Converter().Convert(new[] { null, "2" }, typeof(int?));

 

Converter的擴展

擴展是靈魂,如果沒有擴展功能,這東東和JavaScriptSerializer.ConvertToType()有啥區別,Converter在擴展方面下了一翻功夫。轉換器里包含多個轉換單元,這些單元可以增加、刪除、替換和調整順序,自定義的單元,可以從已有單元派生,也可以完整實現,然后插入到轉換器的轉換單元管理器中,轉換器就升級了。而轉換單元本身也能調用轉換器來轉換,這就形成一種可擴展的遞歸。

關系代碼如下:

 /// <summary>
        /// 類型轉換
        /// </summary>
        public Converter()
        {
            this.Items = new ContertItems()
                .AddLast<NoConvert>()
                .AddLast<NullConvert>()
                .AddLast<PrimitiveContert>()
                .AddLast<NullableConvert>()
                .AddLast<DictionaryConvert>()
                .AddLast<ArrayConvert>()
                .AddLast<DynamicObjectConvert>();
        }
轉換器由轉換單元組成
 /// <summary>
    /// 定義類型轉換單元
    /// </summary>
    public interface IConvert
    {
        /// <summary>
        /// 將value轉換為目標類型
        /// 並將轉換所得的值放到result
        /// 如果不支持轉換,則返回false
        /// </summary>
        /// <param name="converter">轉換器實例</param>
        /// <param name="value">要轉換的值</param>
        /// <param name="targetType">轉換的目標類型</param>
        /// <param name="result">轉換結果</param>
        /// <returns>如果不支持轉換,則返回false</returns>
        bool Convert(Converter converter, object value, Type targetType, out object result);
    }
轉換單元可以調用轉換器


刪除轉換單元:

var converter = new Converter();
converter.Items.Remove<DynamicObjectConvert>();

增加轉換單元:

編寫一個單元,實現IConvert接口,比如 class JObjectConvert:IConvert{},然后就可以把這個轉換單元添加到轉換器實例中,

var converter = new Converter();
converter.Items.AddFrist<JObjectConvert>();

轉換單元重寫:

比如從string轉換為decimal類時,要求5位小數,我們可以寫一個單元,class MyPrimitiveContert:PrimitiveContert{},然后改寫里面的Convert方法,再把MyPrimitiveContert替換轉換器里的PrimitiveContert單元

var converter = new Converter();
converter.Items.Replace<PrimitiveContert, MyPrimitiveContert>();

后記

之所以寫這個東西,是因為我的NetworkSocket組件里websocket部分很需要一個靈活的類型轉換器,客戶端發送{api:"login",parameters:[{account:"admin",password:"123456"}]}這樣結構的Json給服務器,服務要解析這個json然后反射執行Login(Userinfo user)這個方法。

這里parameters數組里內容的類型是根據api的名稱而定的,而要解析到api的內容,又要知道整個json的結構,形成蛋和雞。只有將json解析為動態類型,才能滿足要求,而JavaScriptSerializer反序列化為動態類型時,實際上是json對象轉換為字典,json數組轉換為ArrayList,其它基本類型差不多一一對應,枚舉類型看情況;如果使用Json.Net解析,json對象轉換為JObject動態類型,json數組轉換為JArray,一些基本類型一般會對應JValue。

當把序列化和反序列化抽象或定義為接口的時候,JavaScriptSerializer.Converter方法就無力了,它沒法轉換JObject這些類型,也沒有擴展的入口點,還有就是在.net core上也用不了。而Converter只需要添加一個單元轉換單元,用來實現Json.Net里面幾個動態類型轉換為Api參數的類型,就可以達到完美的轉換效果。

 


免責聲明!

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



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