zoukankan      html  css  js  c++  java
  • 一种优雅的条件引用第三方.net库的方法

    1.遇到的问题 

    今年我一直在开发一个WebApiClient库,旨在.net下能像java的retrofit一样,方便地请求服务端的http接口。在这restful api盛行的年代,json的身影无处不在,.net framework自然也有json库,System.Web.Script.Serialization.JavaScriptSerializer就是其中一个,但综合性较好的,还是第三方的json.net。在开发WebApiClient过程中,我一直没有依赖json.net,原因是:如果我的WebApiClient依赖json.net的版本是6.0,某个第三方库ThirdLib依赖的json.net版本是7.0,在项目中会无法都使用WebApiClient和ThirdLib,原因是他们依赖的json.net版本不一样而决生冲突,给使用者解决起来很非常麻烦。

    2.期望的效果

    我期望的效果是,如果引用WebApiClient库的项目有使用到json.net,那么WebApiClient在json序列化时,就使用json.net,否则使用.net framework的System.Web.Script.Serialization.JavaScriptSerializer。这就要求我在开发WebApiClient的时候,不能直接引用json.net来开发,只能在运行时检测应用程序域是否已加载了json.net,从而反射调用json.net来进行序列化。

    想要的效果是这样的

    /// <summary>
    /// 反序列化对象
    /// </summary>
    /// <param name="json">json</param>
    /// <param name="objType">对象类型</param>
    /// <returns></returns>
    public object Deserialize(string json, Type objType)
    {
        if (string.IsNullOrEmpty(json))
        {
            return null;
        }
    
        if (JsonNet.IsSupported == true)
        {
            return JsonNet.DeserializeObject(json, objType);
        }
    
        var serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
        return serializer.Deserialize(json, objType);
    }

    3.解决的方案

    在运行时检测应用程序域是否已加载了json.net,从而反射调用json.net来进行序列化。

    实现中的难点:

    1、如果检测是否加载了Json.net

    2、在检测之后,才加载Json.net怎么办

    3、怎么样减少反射的性能损耗

    难点的解决:

    1、使用AppDomain.CurrentDomain.GetAssemblies()方法获取当前程序域目前已加载的程序集,判断是否有Json.net的程序集;

    2、监听AppDomain.CurrentDomain.AssemblyLoad事件,订阅新加载的程序集是否为Json.net的程序集;

    3、将Newtonsoft.Json.JsonConvert的SerializeObject和DeserializeObject方法生成强类型委托,缓存起来等待调用;

    完整代码实现:

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Reflection;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace WebApiClient
    {
        /// <summary>
        /// 提供Json.net无引用调用
        /// </summary>
        static class JsonNet
        {
            /// <summary>
            /// Json.Net程序集名称
            /// </summary>
            private static readonly string jsonNetAssemblyName = "Newtonsoft.Json";
    
            /// <summary>
            /// JsonConvert类名
            /// </summary>
            private static readonly string jsonNetJsonConvertTypeName = "Newtonsoft.Json.JsonConvert";
    
            /// <summary>
            /// 序列化方法的委托
            /// </summary>
            private static Func<object, string> serializeFunc = null;
    
            /// <summary>
            /// 反序列化方法的委托
            /// </summary>
            private static Func<string, Type, object> deserializeFunc = null;
    
            /// <summary>
            /// 获取是否得到支持
            /// </summary>
            public static bool IsSupported = false;
    
            /// <summary>
            /// Json.net
            /// </summary>
            static JsonNet()
            {
                AppDomain.CurrentDomain.AssemblyLoad += (s, e) => InitJsonNet(e.LoadedAssembly);
                InitJsonNet(AppDomain.CurrentDomain.GetAssemblies());
            }
    
            /// <summary>
            /// 序列化对象
            /// </summary>
            /// <param name="obj">对象</param>
            /// <returns></returns>
            public static string SerializeObject(object obj)
            {
                return JsonNet.serializeFunc.Invoke(obj);
            }
    
            /// <summary>
            /// 反序列化为对象
            /// </summary>
            /// <param name="json">json文本</param>
            /// <param name="type">对象类型</param>
            /// <returns></returns>
            public static object DeserializeObject(string json, Type type)
            {
                return JsonNet.deserializeFunc.Invoke(json, type);
            }
    
            /// <summary>
            /// 初始化json.net
            /// </summary>
            /// <param name="assemblies">查找的程序集</param>
            private static void InitJsonNet(params Assembly[] assemblies)
            {
                if (JsonNet.IsSupported == true)
                {
                    return;
                }
    
                var jsonNetAssembly = assemblies
                    .FirstOrDefault(item => item.GetName().Name.Equals(jsonNetAssemblyName, StringComparison.OrdinalIgnoreCase));
    
                if (jsonNetAssembly == null)
                {
                    return;
                }
    
                var jsonConvertType = jsonNetAssembly.GetType(jsonNetJsonConvertTypeName, false);
                if (jsonConvertType == null)
                {
                    return;
                }
    
                serializeFunc = CreateSerializeObjectFunc(jsonConvertType);
                deserializeFunc = CreateDeserializeObjectFunc(jsonConvertType);
                JsonNet.IsSupported = serializeFunc != null && deserializeFunc != null;
            }
    
            /// <summary>
            /// 创建SerializeObject方法的委托
            /// </summary>
            /// <param name="classType">JsonConvert类型</param>
            /// <returns></returns>
            private static Func<object, string> CreateSerializeObjectFunc(Type classType)
            {
                var method = classType.GetMethod("SerializeObject", new[] { typeof(object) });
                if (method == null)
                {
                    return null;
                }
                return (Func<object, string>)method.CreateDelegate(typeof(Func<object, string>));
            }
    
            /// <summary>
            /// 创建DeserializeObject方法的委托
            /// </summary>
            /// <param name="classType">JsonConvert类型</param>
            /// <returns></returns>
            private static Func<string, Type, object> CreateDeserializeObjectFunc(Type classType)
            {
                var method = classType.GetMethod("DeserializeObject", new[] { typeof(string), typeof(Type) });
                if (method == null)
                {
                    return null;
                }
                return (Func<string, Type, object>)method.CreateDelegate(typeof(Func<string, Type, object>));
            }
        }
    }

    关于WebApiClient

    这是一个让你描述做什么请求,而不是叫你如何请求的httpClient客户端项目,关注一下,你会眼前一亮,get到新思想。

    github:https://github.com/xljiulang/WebApiClient

  • 相关阅读:
    测试随笔
    代码规范与计划
    WeChair项目Alpha冲刺(8/10)
    WeChair项目Alpha冲刺(7/10)
    WeChair项目Alpha冲刺(6/10)
    WeChair项目Alpha冲刺(5/10)
    WeChair项目Alpha冲刺(4/10)
    WeChair项目Alpha冲刺(3/10)
    WeChair项目Alpha冲刺(2/10)
    代码规范
  • 原文地址:https://www.cnblogs.com/kewei/p/8228343.html
Copyright © 2011-2022 走看看