JsonConvertHolder.cs 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. using System;
  2. using System.Collections.Concurrent;
  3. using System.Linq;
  4. using System.Linq.Expressions;
  5. using System.Reflection;
  6. using Newtonsoft.Json;
  7. namespace VCommon.VAutoMapper.Internals
  8. {
  9. internal static class JsonConvertHolder
  10. {
  11. private static readonly ConcurrentDictionary<Type, JsonConverter> ConverterInstances = new ConcurrentDictionary<Type, JsonConverter>();
  12. private static readonly ConcurrentDictionary<Tuple<PropertyInfo, PropertyInfo>, Expression<Func<string, Type, object>>> CachedDeserializationExpression = new ConcurrentDictionary<Tuple<PropertyInfo, PropertyInfo>, Expression<Func<string, Type, object>>>();
  13. private static readonly ConcurrentDictionary<Tuple<PropertyInfo, PropertyInfo>, Expression<Func<object, string>>> CachedSerializationExpression = new ConcurrentDictionary<Tuple<PropertyInfo, PropertyInfo>, Expression<Func<object, string>>>();
  14. private static JsonConverter GetConverterInstance(Type converterType)
  15. {
  16. if (ConverterInstances.TryGetValue(converterType, out var instance)) return instance;
  17. instance = Activator.CreateInstance(converterType) as JsonConverter;
  18. ConverterInstances[converterType] = instance ?? throw new ArgumentException($"type must extend from {nameof(JsonConverter)}");
  19. return instance;
  20. }
  21. public static Expression<Func<string, Type, object>> GetDeserializationExpression(PropertyInfo fromProp, PropertyInfo toProp)
  22. {
  23. var pair = new Tuple<PropertyInfo, PropertyInfo>(fromProp, toProp);
  24. if (CachedDeserializationExpression.TryGetValue(pair, out var exp)) return exp;
  25. var attr = toProp.GetCustomAttribute<AutoMapJsonConvertAttribute>();
  26. if (0 == attr.Converters.Count)
  27. {
  28. exp = (s, t) => JsonConvert.DeserializeObject(s, t);
  29. CachedDeserializationExpression[pair] = exp;
  30. }
  31. else
  32. {
  33. var converters = attr.Converters.Select(GetConverterInstance).ToArray();
  34. var setting = new JsonSerializerSettings { Converters = converters };
  35. exp = CachedDeserializationExpression[pair] = (s, t) => JsonConvert.DeserializeObject(s, t, setting);
  36. }
  37. return exp;
  38. }
  39. public static Expression<Func<object, string>> GetSerializationExpression(PropertyInfo fromProp, PropertyInfo toProp)
  40. {
  41. var pair = new Tuple<PropertyInfo, PropertyInfo>(fromProp, toProp);
  42. if (CachedSerializationExpression.TryGetValue(pair, out var exp)) return exp;
  43. var attr = fromProp.GetCustomAttribute<AutoMapJsonConvertAttribute>();
  44. if (0 == attr.Converters.Count)
  45. {
  46. exp = CachedSerializationExpression[pair] = o => JsonConvert.SerializeObject(o);
  47. }
  48. else
  49. {
  50. var converters = attr.Converters.Select(GetConverterInstance).ToArray();
  51. var setting = new JsonSerializerSettings { Converters = converters };
  52. exp = CachedSerializationExpression[pair] = o => JsonConvert.SerializeObject(o, setting);
  53. }
  54. return exp;
  55. }
  56. }
  57. }