FieldOrProperty.cs 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. // $Id$
  2. using System;
  3. using System.Reflection;
  4. using System.Collections;
  5. using System.Collections.Generic;
  6. namespace LispReader
  7. {
  8. public delegate void PropertyChangedHandler(object Object, FieldOrProperty field, object oldValue);
  9. /// <summary>
  10. /// Oreginal base class (MemberInfo) can't Get/SetValue and this class allows it.
  11. /// One code can work with FieldInfo or PropertyInfo as if there was no difference between them. + can raise event when Changed
  12. /// It's a kind of hack, however, because we can't "rebase" a class.
  13. ///</summary>
  14. public abstract class FieldOrProperty
  15. {
  16. private static Dictionary<FieldInfo, FieldOrProperty> fields = new Dictionary<FieldInfo, FieldOrProperty>();
  17. private static Dictionary<PropertyInfo, FieldOrProperty> properties = new Dictionary<PropertyInfo, FieldOrProperty>();
  18. private class FieldOrPropertyLister : IEnumerable<FieldOrProperty>
  19. {
  20. private Type type;
  21. public FieldOrPropertyLister(Type type)
  22. {
  23. this.type = type;
  24. }
  25. private IEnumerator<FieldOrProperty> GetEnumerator()
  26. {
  27. foreach(FieldInfo field in type.GetFields()) {
  28. yield return Lookup(field);
  29. }
  30. foreach(PropertyInfo property in type.GetProperties()) {
  31. yield return Lookup(property);
  32. }
  33. }
  34. IEnumerator<FieldOrProperty> IEnumerable<FieldOrProperty>.GetEnumerator()
  35. {
  36. return GetEnumerator();
  37. }
  38. IEnumerator IEnumerable.GetEnumerator()
  39. {
  40. return GetEnumerator();
  41. }
  42. }
  43. /// <summary> Use this event, if you want to recieve events for this Field only </summary>
  44. public event PropertyChangedHandler Changed;
  45. /// <summary> Use this event, if you want to get all changed events and implement custom filter (e.g. field name) </summary>
  46. public static event PropertyChangedHandler AnyFieldChanged;
  47. public static IEnumerable<FieldOrProperty> GetFieldsAndProperties(Type type)
  48. {
  49. return new FieldOrPropertyLister(type);
  50. }
  51. public abstract string Name {
  52. get;
  53. }
  54. public abstract Type Type {
  55. get;
  56. }
  57. public abstract void SetValue(object Object, object Value);
  58. public abstract object GetValue(object Object);
  59. public abstract object GetCustomAttribute(Type attributeType);
  60. public abstract object[] GetCustomAttributes(Type attributeType);
  61. public static FieldOrProperty Lookup(FieldInfo field) {
  62. if (!fields.ContainsKey(field))
  63. fields.Add(field, new Field(field));
  64. return fields[field];
  65. }
  66. public static FieldOrProperty Lookup(PropertyInfo property) {
  67. if (!properties.ContainsKey(property))
  68. properties.Add(property, new Property(property));
  69. return properties[property];
  70. }
  71. protected void FireChanged(object Object, FieldOrProperty field, object oldValue){
  72. if (Changed != null)
  73. Changed(Object, field, oldValue);
  74. if (AnyFieldChanged != null)
  75. AnyFieldChanged(Object, field, oldValue);
  76. }
  77. /// <summary> Code uses this to notify editors when only part of object changes (but it's adress not). </summary>
  78. public void FireChanged(object Object) {
  79. FireChanged(Object, this, this.GetValue(Object));
  80. }
  81. private class Field : FieldOrProperty{
  82. private FieldInfo field;
  83. public Field(FieldInfo field)
  84. {
  85. this.field = field;
  86. }
  87. public override string Name {
  88. get {
  89. return field.Name;
  90. }
  91. }
  92. public override Type Type {
  93. get {
  94. return field.FieldType;
  95. }
  96. }
  97. public override void SetValue(object Object, object value)
  98. {
  99. object oldValue = field.GetValue(Object);
  100. field.SetValue(Object, value);
  101. if (oldValue != value)
  102. FireChanged(Object, this, oldValue);
  103. }
  104. public override object GetValue(object Object)
  105. {
  106. return field.GetValue(Object);
  107. }
  108. public override object GetCustomAttribute(Type attributeType)
  109. {
  110. return Attribute.GetCustomAttribute(field, attributeType);
  111. }
  112. public override object[] GetCustomAttributes(Type attributeType)
  113. {
  114. return Attribute.GetCustomAttributes(field, attributeType);
  115. }
  116. }
  117. private class Property : FieldOrProperty{
  118. private PropertyInfo property;
  119. public Property(PropertyInfo property)
  120. {
  121. this.property = property;
  122. }
  123. public override string Name {
  124. get {
  125. return property.Name;
  126. }
  127. }
  128. public override Type Type {
  129. get {
  130. return property.PropertyType;
  131. }
  132. }
  133. public override void SetValue(object Object, object value)
  134. {
  135. object oldValue = property.GetValue(Object, null);
  136. property.SetValue(Object, value, null);
  137. if (oldValue != value)
  138. FireChanged(Object, this, oldValue);
  139. }
  140. public override object GetValue(object Object)
  141. {
  142. return property.GetValue(Object, null);
  143. }
  144. public override object GetCustomAttribute(Type attributeType)
  145. {
  146. return Attribute.GetCustomAttribute(property, attributeType);
  147. }
  148. public override object[] GetCustomAttributes(Type attributeType)
  149. {
  150. return Attribute.GetCustomAttributes(property, attributeType);
  151. }
  152. }
  153. }
  154. }