Advertisement
Guest User

Untitled

a guest
Jul 25th, 2017
71
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.85 KB | None | 0 0
  1. public interface IConfiguration
  2. {
  3. [CanBeNull]
  4. T GetValue<T>([NotNull] CaseInsensitiveString name);
  5.  
  6. void Save([NotNull] CaseInsensitiveString name, [NotNull] object value);
  7. }
  8.  
  9. public static class ConfigurationExtensions
  10. {
  11. public static IConfiguration SetValue<T>(this IConfiguration configuration, Expression<Func<T>> expression)
  12. {
  13. var value = configuration.GetValue(expression);
  14. expression.SetValue(value);
  15. return configuration;
  16. }
  17.  
  18. public static T GetValue<T>(this IConfiguration config, Expression<Func<T>> expression)
  19. {
  20. var memberExpr = expression.Body as MemberExpression ?? throw new ArgumentException("Expression must be a member expression.");
  21. var name = $"{memberExpr.Member.DeclaringType.Namespace}+{memberExpr.Member.DeclaringType.Name}.{memberExpr.Member.Name}";
  22. return config.GetValue<T>(name);
  23. }
  24. }
  25.  
  26. public static class MemberSetter
  27. {
  28. public static void SetValue<T>([NotNull] this Expression<Func<T>> expression, object value)
  29. {
  30. if (expression == null) throw new ArgumentNullException(nameof(expression));
  31. if (expression.Body is MemberExpression memberExpression)
  32. {
  33. var obj = GetObject(memberExpression.Expression);
  34.  
  35. switch (memberExpression.Member.MemberType)
  36. {
  37. case MemberTypes.Property:
  38. var property = (PropertyInfo)memberExpression.Member;
  39. if (property.CanWrite)
  40. {
  41. ((PropertyInfo)memberExpression.Member).SetValue(obj, value);
  42. }
  43. else
  44. {
  45. var bindingFlags = BindingFlags.NonPublic | (obj == null ? BindingFlags.Static : BindingFlags.Instance);
  46. var backingField = (obj?.GetType() ?? property.DeclaringType).GetField($"<{property.Name}>k__BackingField", bindingFlags);
  47. if (backingField == null)
  48. {
  49. throw new BackingFieldNotFoundException(property.Name);
  50. }
  51. backingField.SetValue(obj, value);
  52. }
  53. break;
  54. case MemberTypes.Field:
  55. ((FieldInfo)memberExpression.Member).SetValue(obj, value);
  56. break;
  57. default:
  58. throw new ArgumentException($"Member must be either a {nameof(MemberTypes.Property)} or a {nameof(MemberTypes.Field)}.");
  59. }
  60. }
  61. else
  62. {
  63. throw new ArgumentException($"Expression must be a {nameof(MemberExpression)}.");
  64. }
  65. }
  66.  
  67. private static object GetObject(Expression expression)
  68. {
  69. // This is a static class.
  70. if (expression == null)
  71. {
  72. return null;
  73. }
  74. if (expression is MemberExpression anonymousMemberExpression)
  75. {
  76. // Extract constant value from the anonyous-wrapper
  77. var container = ((ConstantExpression)anonymousMemberExpression.Expression).Value;
  78. return ((FieldInfo)anonymousMemberExpression.Member).GetValue(container);
  79. }
  80. else
  81. {
  82. return ((ConstantExpression)expression).Value;
  83. }
  84. }
  85. }
  86.  
  87. [TestMethod]
  88. public void Load_InstanceMembers_OnTheType_Loaded()
  89. {
  90. var config = new Configuration(new Memory
  91. {
  92. { "PublicProperty", "a" },
  93. { "PrivateProperty", "b" },
  94. { "PublicField", "c" },
  95. { "PrivateField", "d" },
  96. { "PrivateReadOnlyField", "e" },
  97. });
  98.  
  99. var x = new InstanceClass(config);
  100.  
  101. config.SetValue(() => x.PublicProperty);
  102. config.SetValue(() => x.PublicField);
  103. config.SetValue(() => x.PublicReadOnlyProperty);
  104.  
  105. CollectionAssert.AreEqual(new[] { "a", null, "c", null, null, "f" }, x.GetValues().ToList());
  106. }
  107.  
  108. [TestMethod]
  109. public void Load_InstanceMembers_InsideConstructor_Loaded()
  110. {
  111. var config = new Configuration(new Memory
  112. {
  113. { "PublicProperty", "a" },
  114. { "PrivateProperty", "b" },
  115. { "PublicField", "c" },
  116. { "PrivateField", "d" },
  117. { "PrivateReadOnlyField", "e" },
  118. { "PublicReadOnlyProperty", "f" },
  119. });
  120.  
  121. var x = new InstanceClass(config);
  122.  
  123. CollectionAssert.AreEqual(new[] { "a", "b", "c", "d", "e", "f" }, x.GetValues().ToList());
  124. }
  125.  
  126. [TestMethod]
  127. public void Load_StaticMembers_Loaded()
  128. {
  129. var config = new Configuration(new Memory
  130. {
  131. { "PublicProperty", "a" },
  132. { "PrivateProperty", "b" },
  133. { "PublicField", "c" },
  134. { "PrivateField", "d" },
  135. { "PrivateReadOnlyField", "e" },
  136. { "PublicReadOnlyProperty", "f" },
  137. });
  138.  
  139. config.SetValue(() => StaticClass.PublicProperty);
  140. config.SetValue(() => StaticClass.PublicField);
  141. config.SetValue(() => StaticClass.PublicReadOnlyProperty);
  142.  
  143. CollectionAssert.AreEqual(new[] { "a", null, "c", null, null, "f" }, StaticClass.GetValues().ToList());
  144. }
  145.  
  146. public class InstanceClass
  147. {
  148. public InstanceClass() { }
  149.  
  150. public InstanceClass(IConfiguration config)
  151. {
  152. config.SetValue(() => PublicProperty);
  153. config.SetValue(() => PrivateProperty);
  154. config.SetValue(() => PublicField);
  155. config.SetValue(() => PrivateField);
  156. config.SetValue(() => PrivateReadOnlyField);
  157. config.SetValue(() => PublicReadOnlyProperty);
  158. }
  159.  
  160. public string PublicProperty { get; set; }
  161.  
  162. private string PrivateProperty { get; set; }
  163.  
  164. public string PublicField;
  165.  
  166. private string PrivateField;
  167.  
  168. private readonly string PrivateReadOnlyField;
  169.  
  170. public string PublicReadOnlyProperty { get; }
  171.  
  172. public IEnumerable<object> GetValues()
  173. {
  174. yield return PublicProperty;
  175. yield return PrivateProperty;
  176. yield return PublicField;
  177. yield return PrivateField;
  178. yield return PrivateReadOnlyField;
  179. yield return PublicReadOnlyProperty;
  180. }
  181. }
  182.  
  183. public static class StaticClass
  184. {
  185. public static string PublicProperty { get; set; }
  186.  
  187. private static string PrivateProperty { get; set; }
  188.  
  189. public static string PublicField;
  190.  
  191. private static string PrivateField;
  192.  
  193. private static readonly string PrivateReadOnlyField;
  194.  
  195. public static string PublicReadOnlyProperty { get; }
  196.  
  197. public static IEnumerable<object> GetValues()
  198. {
  199. yield return PublicProperty;
  200. yield return PrivateProperty;
  201. yield return PublicField;
  202. yield return PrivateField;
  203. yield return PrivateReadOnlyField;
  204. yield return PublicReadOnlyProperty;
  205. }
  206. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement