DynamicJSON.cs 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Dynamic;
  6. using System.Xml.Linq;
  7. using System.Text.Json;
  8. using System.Collections;
  9. namespace EasyDevCore.Common.Wrapper
  10. {
  11. /// <summary>
  12. ///
  13. /// </summary>
  14. public class DynamicJson : DynamicObject
  15. {
  16. private readonly IDictionary<string, object> _dictionary;
  17. /// <summary>
  18. /// Initializes a new instance of the <see cref="DynamicJson"/> class.
  19. /// </summary>
  20. /// <param name="jsonString">The json string.</param>
  21. private DynamicJson(string jsonString):this(JsonSerializer.Deserialize<Dictionary<string, object>>(jsonString))
  22. {
  23. }
  24. /// <summary>
  25. /// Initializes a new instance of the <see cref="DynamicJson"/> class.
  26. /// </summary>
  27. /// <param name="dictionary">The dictionary.</param>
  28. private DynamicJson(IDictionary<string, object> dictionary)
  29. {
  30. _dictionary = dictionary;
  31. }
  32. /// <summary>
  33. /// Parses the specified XML string.
  34. /// </summary>
  35. /// <param name="jsonString">The json string.</param>
  36. /// <returns></returns>
  37. public static DynamicJson Parse(string jsonString)
  38. {
  39. return new DynamicJson(jsonString);
  40. }
  41. /// <summary>
  42. /// Parses the specified dictionary.
  43. /// </summary>
  44. /// <param name="dictionary">The dictionary.</param>
  45. /// <returns></returns>
  46. public static DynamicJson Parse(IDictionary<string, object> dictionary)
  47. {
  48. return new DynamicJson(dictionary);
  49. }
  50. /// <summary>
  51. /// Loads the specified filename.
  52. /// </summary>
  53. /// <param name="filename">The filename.</param>
  54. /// <returns></returns>
  55. public static DynamicJson Load(string filename)
  56. {
  57. return new DynamicJson(System.IO.File.ReadAllText(filename));
  58. }
  59. /// <summary>
  60. /// Provides the implementation for operations that get member values. Classes derived from the <see cref="T:System.Dynamic.DynamicObject" /> class can override this method to specify dynamic behavior for operations such as getting a value for a property.
  61. /// </summary>
  62. /// <param name="binder">Provides information about the object that called the dynamic operation. The <c>binder.Name</c> property provides the name of the member on which the dynamic operation is performed. For example, for the <c>Console.WriteLine(sampleObject.SampleProperty)</c> statement, where <c>sampleObject</c> is an instance of the class derived from the <see cref="T:System.Dynamic.DynamicObject" /> class, <c>binder.Name</c> returns "SampleProperty". The <c>binder.IgnoreCase</c> property specifies whether the member name is case-sensitive.</param>
  63. /// <param name="result">The result of the get operation. For example, if the method is called for a property, you can assign the property value to <paramref name="result" />.</param>
  64. /// <returns>
  65. /// <see langword="true" /> if the operation is successful; otherwise, <see langword="false" />. If this method returns <see langword="false" />, the run-time binder of the language determines the behavior. (In most cases, a run-time exception is thrown.)
  66. /// </returns>
  67. public override bool TryGetMember(GetMemberBinder binder, out object result)
  68. {
  69. if (!_dictionary.TryGetValue(binder.Name, out result))
  70. {
  71. // return null to avoid exception. caller can check for null this way...
  72. result = null;
  73. return true;
  74. }
  75. result = WrapResultObject(result);
  76. return true;
  77. }
  78. /// <summary>
  79. /// Wraps the result object.
  80. /// </summary>
  81. /// <param name="result">The result.</param>
  82. /// <returns></returns>
  83. private static object WrapResultObject(object result)
  84. {
  85. var dictionary = result as IDictionary<string, object>;
  86. if (dictionary != null)
  87. return new DynamicJson(dictionary);
  88. var arrayList = result as ArrayList;
  89. if (arrayList != null && arrayList.Count > 0)
  90. {
  91. return arrayList[0] is IDictionary<string, object>
  92. ? new List<object>(arrayList.Cast<IDictionary<string, object>>().Select(x => new DynamicJson(x)))
  93. : new List<object>(arrayList.Cast<object>());
  94. }
  95. return result;
  96. }
  97. /// <summary>
  98. /// Provides the implementation for operations that get a value by index. Classes derived from the <see cref="T:System.Dynamic.DynamicObject" /> class can override this method to specify dynamic behavior for indexing operations.
  99. /// </summary>
  100. /// <param name="binder">Provides information about the operation.</param>
  101. /// <param name="indexes">The indexes that are used in the operation. For example, for the <c>sampleObject[3]</c> operation in C# (<c>sampleObject(3)</c> in Visual Basic), where <c>sampleObject</c> is derived from the <see langword="DynamicObject" /> class, <c>indexes[0]</c> is equal to 3.</param>
  102. /// <param name="result">The result of the index operation.</param>
  103. /// <returns>
  104. /// <see langword="true" /> if the operation is successful; otherwise, <see langword="false" />. If this method returns <see langword="false" />, the run-time binder of the language determines the behavior. (In most cases, a run-time exception is thrown.)
  105. /// </returns>
  106. public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result)
  107. {
  108. if (indexes.Length == 1 && indexes[0] != null)
  109. {
  110. if (!_dictionary.TryGetValue(indexes[0].ToString(), out result))
  111. {
  112. // return null to avoid exception. caller can check for null this way...
  113. result = null;
  114. return true;
  115. }
  116. result = WrapResultObject(result);
  117. return true;
  118. }
  119. return base.TryGetIndex(binder, indexes, out result);
  120. }
  121. }
  122. }