Design Concepts: Invokable Class

So while working on designing the entity system for the game I ran into a tiny little snag. Due to the way the entities are designed, more on that later, the entities needed a way to access fields, properties, methods, and events on DataObjects but needed to do so without the actual type.

Now by default the DataObject class only has couple of common fields, properties, and methods that are shared between all objects, but for example the entity location component needs access to a “Location” field that the base class does not have, so I did some faffing around and came up with some methods that allow me to use a simple methods to access these fields from the base data object class, but still use them.

So I have made up a simple class, that can be inherited to allow any object that inherits it to have this functionality. It’s a work in progress but more refining and improvements will be added later, but here is an example of how it can be used.

if(DataObject.HasField("nameoffield") {
    DataObject.SetField("nameoffield", value);
}

For those interested here is the current source, at the time of this post, of the invokable class. (View on GitHub)

  1. using System;
  2. using System.Collections.Generic;
  3.  
  4. namespace Astrendaria.Classes
  5. {
  6. /// <summary>
  7. /// Invokable class, defines functions to access fields, properties, events, and methods with a base class.
  8. /// </summary>
  9. public abstract class Invokable
  10. {
  11. /// <summary>
  12. /// Checks to see if the data object has the specified property.
  13. /// </summary>
  14. /// <typeparam name="PType">The return type of the property.</typeparam>
  15. /// <param name="name">The name of the property.</param>
  16. /// <returns>True if found, false if not.</returns>
  17. public virtual bool HasProperty<PType>(string name)
  18. {
  19. // Get the property.
  20. var property = GetType().GetProperty(name, typeof(PType));
  21.  
  22. // Return the value.
  23. return (property != null);
  24. }
  25.  
  26. /// <summary>
  27. /// Gets the value of the specified property.
  28. /// </summary>
  29. /// <typeparam name="PType">The return type of the property.</typeparam>
  30. /// <param name="name">The name of the property.</param>
  31. /// <returns>The value of the property.</returns>
  32. public virtual PType GetProperty<PType>(string name)
  33. {
  34. // Get the property.
  35. var property = GetType().GetProperty(name, typeof(PType));
  36.  
  37. // Check to see if we got it.
  38. if (property != null)
  39. {
  40. // Can we read it.
  41. if (property.CanRead)
  42. {
  43. // Return the value.
  44. return (PType)property.GetValue(this);
  45. }
  46. }
  47.  
  48. // Something went wrong, return the default value.
  49. return default(PType);
  50. }
  51.  
  52. /// <summary>
  53. /// Sets the value of the specified property
  54. /// </summary>
  55. /// <typeparam name="PType">The return type of the property.</typeparam>
  56. /// <param name="name">The name of the property.</param>
  57. /// <param name="value">The new value of the property.</param>
  58. public virtual void SetProperty<PType>(string name, PType value)
  59. {
  60. // Get the property.
  61. var property = GetType().GetProperty(name, typeof(PType));
  62.  
  63. // Check to see if we got it.
  64. if (property != null)
  65. {
  66. // Can we write to it.
  67. if (property.CanWrite)
  68. {
  69. // Change the value.
  70. property.SetValue(this, value);
  71. }
  72. }
  73. }
  74.  
  75. /// <summary>
  76. /// Checks to see if the data object has the specified event.
  77. /// </summary>
  78. /// <typeparam name="EType">The return type of the event.</typeparam>
  79. /// <param name="name">The name of the event.</param>
  80. /// <returns>True if found, false if not.</returns>
  81. public virtual bool HasEvent<EType>(string name)
  82. {
  83. // Get the event.
  84. var e = GetType().GetEvent(name);
  85.  
  86. // Return the value.
  87. return (e != null);
  88. }
  89.  
  90. /// <summary>
  91. /// Adds an event handler to the specified event.
  92. /// </summary>
  93. /// <param name="name">The name of the event.</param>
  94. /// <param name="value">The event handler to add.</param>
  95. public virtual void AddEvent(string name, Delegate value)
  96. {
  97. // Get the event.
  98. var e = GetType().GetEvent(name);
  99.  
  100. // Check to see if we got it.
  101. if (e != null)
  102. {
  103. // Add the event handler.
  104. e.AddEventHandler(this, value);
  105. }
  106. }
  107.  
  108. /// <summary>
  109. /// Removes an event handler to the specified event.
  110. /// </summary>
  111. /// <param name="name">The name of the event.</param>
  112. /// <param name="value">The event handler to remove.</param>
  113. public virtual void RemoveEvent(string name, Delegate value)
  114. {
  115. // Get the event.
  116. var e = GetType().GetEvent(name);
  117.  
  118. // Check to see if we got it.
  119. if (e != null)
  120. {
  121. // Remove the event handler.
  122. e.RemoveEventHandler(this, value);
  123. }
  124. }
  125.  
  126. /// <summary>
  127. /// Checks to see if the data object has the specified field.
  128. /// </summary>
  129. /// <param name="name">The name of the field.</param>
  130. /// <returns>True if found, false if not.</returns>
  131. public virtual bool HasField(string name)
  132. {
  133. // Get the field.
  134. var field = GetType().GetField(name);
  135.  
  136. // Return the value.
  137. return (field != null);
  138. }
  139.  
  140. /// <summary>
  141. /// Gets the value of the specified field.
  142. /// </summary>
  143. /// <typeparam name="FType">The return type of the field.</typeparam>
  144. /// <param name="name">The name of the field.</param>
  145. /// <returns>The value of the field.</returns>
  146. public virtual FType GetField<FType>(string name)
  147. {
  148. // Get the field.
  149. var field = GetType().GetField(name);
  150.  
  151. // Check to see if we got it.
  152. if (field != null)
  153. {
  154. // Return the value.
  155. return (FType)field.GetValue(this);
  156. }
  157.  
  158. // Something went wrong, return the default value.
  159. return default(FType);
  160. }
  161.  
  162. /// <summary>
  163. /// Sets the value of the specified field
  164. /// </summary>
  165. /// <typeparam name="FType">The return type of the field.</typeparam>
  166. /// <param name="name">The name of the field.</param>
  167. /// <param name="value">The new value of the field.</param>
  168. public virtual void SetField<FType>(string name, FType value)
  169. {
  170. // Get the field.
  171. var field = GetType().GetField(name);
  172.  
  173. // Check to see if we got it.
  174. if (field != null)
  175. {
  176. // Change the value.
  177. field.SetValue(this, value);
  178. }
  179. }
  180.  
  181. /// <summary>
  182. /// Invokes the specified method.
  183. /// </summary>
  184. /// <param name="name">The name of the method.</param>
  185. /// <param name="paramaters">THe paramaters of the method.</param>
  186. public virtual void Method(string name, params object[] paramaters)
  187. {
  188. // Check to see if any paramaters were passed.
  189. if (paramaters != null)
  190. {
  191. // Yes, we need to convert them to a type array.
  192. List<Type> ptypes = new List<Type>();
  193.  
  194. // Loop through and get each type.
  195. foreach (var p in paramaters)
  196. {
  197. // Add the type to the list.
  198. ptypes.Add(p.GetType());
  199. }
  200.  
  201. // Now make an array.
  202. var types = ptypes.ToArray();
  203.  
  204. // And do some clean up.
  205. ptypes.Clear();
  206. ptypes = null;
  207.  
  208. // Now try to get the method.
  209. var method = GetType().GetMethod(name, types);
  210.  
  211. // Check to see if the method was found.
  212. if (method != null)
  213. {
  214. // It was, invoke it.
  215. method.Invoke(this, paramaters);
  216. }
  217. }
  218. else
  219. {
  220. // Get the method.
  221. var method = GetType().GetMethod(name);
  222.  
  223. // Check to see if it was found.
  224. if (method != null)
  225. {
  226. // It was, invoke it.
  227. method.Invoke(this, null);
  228. }
  229. }
  230. }
  231. }
  232. }

Leave Comment