C#对象转Dictionary(字典)-使用表达式树高性能字典转换测试对比

C#对象转Dictionary(字典)-使用表达式树高性能字典转换测试对比

对比测试了原生代码转换、反射转换、和使用泛型类缓存的表达式树的转换
在我的电脑上100万次执行上反射差一点,但总体性能差异常不大
具体我也搞不清为什么反射和原生的差异并不是很大,有知道的童学告诉下我

  • 直接上测试代码

using System.Diagnostics;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;


namespace dou7.DB
{
    public class Programe
    {


        public static void Main(params string[] args)
        {
            //People people = new People();
            //people.Age = 97;
            //people.Name = "Test";


            //IDictionary<string, object> dict = new Dictionary<string, object>();

            //Dictionary<string, object> result = DictionaryConverter.ConvertToDictionary(people);

            //Console.WriteLine("Result: " + result.ToJSON());

            for (int i = 0; i < 10; i++)
            {
                DicToObj();

                DicToObjRef();

                DicToObjExp();
            }


        }



        private static void DicToObj()
        {
            People people = new People { Name = "dou7" };
            Stopwatch stopwatch = Stopwatch.StartNew();
            for (int i = 0; i < 1000000; i++)
            {
                Dictionary<string, object> value = new Dictionary<string, object>();

                value.Add("Name", people.Name);
                value.Add("Name2", people.Name2);
                value.Add("Name3", people.Name3);
                value.Add("Name4", people.Name4);
                value.Add("Name5", people.Name5);
                value.Add("Name6", people.Name6);
                value.Add("Name7", people.Name7);
                value.Add("Age", people.Age);
                value.Add("Age2", people.Age2);
                value.Add("Age3", people.Age3);
                value.Add("Age4", people.Age4);
                value.Add("Age5", people.Age5);
                value.Add("Age6", people.Age6);
                value.Add("Age7", people.Age7);
                value.Add("Age8", people.Age8);

                value.Add("Content", people.Content);
                value.Add("Title", people.Title);
            }
            stopwatch.Stop();
            Console.WriteLine("Direct: {0}ms", stopwatch.ElapsedMilliseconds);
        }


        private static void DicToObjRef()
        {
            People people = new People { Name = "dou7" };
            Stopwatch stopwatch = Stopwatch.StartNew();
            for (int i = 0; i < 1000000; i++)
            {
                Dictionary<string, object> value = objToDic(people);
            }
            stopwatch.Stop();
            Console.WriteLine("Reflection: {0}ms", stopwatch.ElapsedMilliseconds);
        }

        private static void DicToObjExp()
        {
            People people = new People { Name = "dou7" };
            Stopwatch stopwatch = Stopwatch.StartNew();
            for (int i = 0; i < 1000000; i++)
            {
                Dictionary<string, object> value = DictionaryConverter.ConvertToDictionary(people);
            }
            stopwatch.Stop();
            Console.WriteLine("Expression: {0}ms", stopwatch.ElapsedMilliseconds);
        }


        public static Dictionary<string, object> objToDic<T>(T obj) where T : class
        {
            Dictionary<string, object> map = new Dictionary<string, object>();
            if (obj == null)
            {
                return map;
            }
            Type t = obj.GetType();
            PropertyInfo[] PropertyList = t.GetProperties();
            foreach (var item in PropertyList)
            {
                string name = item.Name;
                object value = item.GetValue(obj, null);
                map.Add(name, value);
            }
            return map;
        }



    }


    public class People
    {
        public string Name { get; set; } = "测试123";

        public string Name2 { get; set; } = "测试123";
        public string Name3 { get; set; } = "测试123";
        public string Name4 { get; set; } = "测试123";
        public string Name5 { get; set; } = "测试123";
        public string Name6 { get; set; } = "测试123";
        public string Name7 { get; set; } = "测试123";

        public int Age { get; set; } = 123;

        public int Age2 { get; set; } = 123;
        public int Age3 { get; set; } = 123;


        public int Age4 { get; set; } = 123;
        public int Age5 { get; set; } = 123;
        public int Age6 { get; set; } = 123;
        public int Age7 { get; set; } = 123;

        public AAA Age8 { get; set; } = AAA.d;


        public string Title = "Test";

        public string Content { get; set; } = "测试内容";
    }

    public enum AAA
    {
        a, b, c, d
    }


    /// <summary>
    /// 对象转字典Mapper
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public static class DictionaryMapper<T> where T : class
    {
        public readonly static Func<T, Dictionary<string, object>> ExpressionMapCache;
        static DictionaryMapper()
        {
            if (ExpressionMapCache == null)
            {
                ExpressionMapCache = GetExpression();
            }
        }

        /// <summary>
        /// 获取对象转字典的表达式树
        /// </summary>
        /// <returns></returns>
        private static Func<T, Dictionary<string, object>> GetExpression()
        {

            Type objType = typeof(T);
            //定义传入的对象参数
            ParameterExpression parameterExpr = Expression.Parameter(objType);

            //字典项添加方法
            MethodInfo addMethod = typeof(Dictionary<string, object>).GetMethod("Add")!;
            var elementInitList = new List<ElementInit>();
            var properties = objType.GetMembers(BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetProperty).Where(m => m is FieldInfo || m is PropertyInfo);
            foreach (var property in properties)
            {
                //读取对象的属性值
                //MethodCallExpression getterExpr = Expression.Call(parameterExpr, property.GetMethod!);
                MemberExpression memberExpr = Expression.PropertyOrField(parameterExpr, property.Name);
                UnaryExpression convertGetterExpr = Expression.Convert(memberExpr, typeof(object));

                //var getterExprBlock = Expression.Block(new ParameterExpression[] { parameterExpr }, getterExpr);
                //使用添加方法初始化字典项
                ElementInit elementInit = Expression.ElementInit(addMethod, Expression.Constant(property.Name), convertGetterExpr);
                elementInitList.Add(elementInit);
            }

            //创建字典对象表达式
            NewExpression newDicExpr = Expression.New(typeof(Dictionary<string, object>));
            //初始化字典列表
            ListInitExpression listInitExpr = Expression.ListInit(newDicExpr, elementInitList);

            Func<T, Dictionary<string, object>> lambdaFunc = Expression.Lambda<Func<T, Dictionary<string, object>>>(listInitExpr, parameterExpr).Compile();

            return lambdaFunc;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static Dictionary<string, object> ConvertToDictionary(T obj)
        {
            return ExpressionMapCache(obj);
        }


    }


    /// <summary>
    /// 字典转换器,使用表达式树将对象转为字典
    /// </summary>
    public class DictionaryConverter
    {

        /// <summary>
        /// 对象转为字典
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="obj">对象</param>
        /// <returns></returns>
        public static Dictionary<string, object> ConvertToDictionary<T>(T obj) where T : class
        {
            return DictionaryMapper<T>.ConvertToDictionary(obj);
        }
    }

}
  • 测试结果图,循环执行了10次对比:
    环境 :.net7

在这里插入图片描述

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

北海山人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值