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