BsManagedSerializableDictionary.h 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. #pragma once
  2. #include "BsScriptEnginePrerequisites.h"
  3. #include "BsIReflectable.h"
  4. #include <mono/jit/jit.h>
  5. namespace BansheeEngine
  6. {
  7. /**
  8. * @brief Contains key and value data used for serializing a managed dictionary.
  9. */
  10. struct BS_SCR_BE_EXPORT ManagedSerializableDictionaryKeyValue : public IReflectable
  11. {
  12. ManagedSerializableDictionaryKeyValue() {}
  13. ManagedSerializableDictionaryKeyValue(const ManagedSerializableFieldDataPtr& key,
  14. const ManagedSerializableFieldDataPtr& value);
  15. ManagedSerializableFieldDataPtr key;
  16. ManagedSerializableFieldDataPtr value;
  17. /************************************************************************/
  18. /* RTTI */
  19. /************************************************************************/
  20. public:
  21. friend class ManagedSerializableDictionaryKeyValueRTTI;
  22. static RTTITypeBase* getRTTIStatic();
  23. virtual RTTITypeBase* getRTTI() const override;
  24. };
  25. /**
  26. * @brief Allows access to an underlying managed dictionary, or a cached version of that dictionary that
  27. * can be serialized/deserialized.
  28. *
  29. * @note This class can be in two states:
  30. * - Linked - When the object has a link to a managed object. This is the default
  31. * state when a new instance of ManagedSerializableObject is created.
  32. * Any operations during this state will operate directly on the linked
  33. * managed object.
  34. * - Serialized - When the object has no link to the managed object but instead just
  35. * contains cached object and field data that may be used for initializing
  36. * a managed object. Any operations during this state will operate
  37. * only on the cached internal data.
  38. * You can transfer between these states by calling serialize(linked->serialized) &
  39. * deserialize (serialized->linked).
  40. *
  41. */
  42. class BS_SCR_BE_EXPORT ManagedSerializableDictionary : public IReflectable
  43. {
  44. private:
  45. struct ConstructPrivately {};
  46. /**
  47. * @brief Generates a hash value for field data.
  48. */
  49. struct BS_SCR_BE_EXPORT Hash
  50. {
  51. inline size_t operator()(const ManagedSerializableFieldDataPtr& x) const;
  52. };
  53. /**
  54. * @brief Compares two field data objects.
  55. */
  56. struct BS_SCR_BE_EXPORT Equals
  57. {
  58. inline bool operator()(const ManagedSerializableFieldDataPtr& a, const ManagedSerializableFieldDataPtr& b) const;
  59. };
  60. public:
  61. typedef UnorderedMap<ManagedSerializableFieldDataPtr, ManagedSerializableFieldDataPtr> CachedEntriesMap;
  62. /**
  63. * @brief Helper class that enumerates over all entires in a managed dictionary. Operates on
  64. * managed object if the parent dictionary is in linked state, or on cached data otherwise.
  65. */
  66. class Enumerator
  67. {
  68. public:
  69. /**
  70. * @brief Constructs a new enumerator for the provided managed object.
  71. *
  72. * @param instance Managed instance of type System.Collections.Generic.Dictionary.
  73. * @param parent Serializable parent of the managed instance.
  74. */
  75. Enumerator(MonoObject* instance, const ManagedSerializableDictionary* parent);
  76. /**
  77. * @brief Returns the wrapped key data at the current enumerator position.
  78. * Only valid to call this if enumerator is valid (i.e. last call to
  79. * ::moveNext returned true).
  80. */
  81. ManagedSerializableFieldDataPtr getKey() const;
  82. /**
  83. * @brief Returns the wrapped value data at the current enumerator position.
  84. * Only valid to call this if enumerator is valid (i.e. last call to
  85. * ::moveNext returned true).
  86. */
  87. ManagedSerializableFieldDataPtr getValue() const;
  88. /**
  89. * @brief Moves the enumerator to the next position. Initially enumerator is
  90. * at an invalid position and must be called at least once before accesing
  91. * its data.
  92. *
  93. * @return Returns if the enumerator is at valid position. When the enumerator returns
  94. * false it means there are no more elements to enumerate.
  95. */
  96. bool moveNext();
  97. private:
  98. MonoObject* mInstance;
  99. MonoObject* mCurrent;
  100. CachedEntriesMap::const_iterator mCachedIter;
  101. bool mIteratorInitialized;
  102. const ManagedSerializableDictionary* mParent;
  103. };
  104. public:
  105. ManagedSerializableDictionary(const ConstructPrivately& dummy, const ManagedSerializableTypeInfoDictionaryPtr& typeInfo, MonoObject* managedInstance);
  106. ManagedSerializableDictionary(const ConstructPrivately& dummy);
  107. /**
  108. * @brief Returns the internal managed instance of the dictionary. This will return null if
  109. * the object is in serialized mode.
  110. */
  111. MonoObject* getManagedInstance() const { return mManagedInstance; }
  112. /**
  113. * @brief Returns the type information for the internal dictionary.
  114. */
  115. ManagedSerializableTypeInfoDictionaryPtr getTypeInfo() const { return mDictionaryTypeInfo; }
  116. /**
  117. * @brief Returns the dictionary value at the specified key. If the key doesn't exist
  118. * the default value for the type is returned. Operates on managed object if in
  119. * linked state, or on cached data otherwise.
  120. *
  121. * @param key Wrapper around the key data at which to retrieve the value.
  122. *
  123. * @return A wrapper around the value in the dictionary at the specified key.
  124. */
  125. ManagedSerializableFieldDataPtr getFieldData(const ManagedSerializableFieldDataPtr& key);
  126. /**
  127. * @brief Sets the dictionary value at the specified key. Operates on managed object if in
  128. * linked state, or on cached data otherwise.
  129. *
  130. * @param key Wrapper around the key data at which to set the value.
  131. * @param val Wrapper around the value to set at the specified key.
  132. */
  133. void setFieldData(const ManagedSerializableFieldDataPtr& key, const ManagedSerializableFieldDataPtr& val);
  134. /**
  135. * @brief Deletes the key/value pair at the specified key. If the key doesn't exist
  136. * this operation does nothing. Operates on managed object if in linked state,
  137. * or on cached data otherwise.
  138. *
  139. * @param key Wrapper around the key data at which to delete the value.
  140. */
  141. void removeFieldData(const ManagedSerializableFieldDataPtr& key);
  142. /**
  143. * @brief Checks if the dictionary contains the specified key. Operates on managed object
  144. * if in linked state, or on cached data otherwise.
  145. *
  146. * @param key Wrapper around the key data which to check.
  147. */
  148. bool contains(const ManagedSerializableFieldDataPtr& key) const;
  149. /**
  150. * @brief Returns an enumerator object that allows you to iterate over
  151. * all key/value pairs in the dictionary.
  152. */
  153. Enumerator getEnumerator() const;
  154. /**
  155. * @brief Serializes the internal managed object into a set of cached data that can be saved
  156. * in memory/disk and can be deserialized later. Does nothing if object is already is
  157. * serialized mode. When in serialized mode the reference to the managed instance will be lost.
  158. */
  159. void serialize();
  160. /**
  161. * @brief Deserializes a set of cached data into a managed object. This action may fail in case the cached
  162. * data contains a type that no longer exists. You may check if it completely successfully if ::getManagedInstance
  163. * returns non-null after.
  164. *
  165. * This action transfers the object into linked mode. All further operations will operate directly on the managed instance
  166. * and the cached data will be cleared. If you call this method on an already linked object the old object will be
  167. * replaced and initialized with empty data (since cached data does not exist).
  168. */
  169. void deserialize();
  170. /**
  171. * @brief Creates a managed serializable dictionary that references an existing managed dictionary. Created object will be in linked mode.
  172. *
  173. * @param managedInstance Constructed managed instance of the dictionary to link with. Its type must correspond with the provided type info.
  174. * @param typeInfo Type information for the dictionary and its key/value pair.
  175. */
  176. static ManagedSerializableDictionaryPtr createFromExisting(MonoObject* managedInstance, const ManagedSerializableTypeInfoDictionaryPtr& typeInfo);
  177. /**
  178. * @brief Creates a managed serializable dictionary that creates and references a brand new managed dictionary instance.
  179. *
  180. * @param typeInfo Type of the dictionary to create.
  181. */
  182. static ManagedSerializableDictionaryPtr createNew(const ManagedSerializableTypeInfoDictionaryPtr& typeInfo);
  183. /**
  184. * @brief Creates a managed dictionary instance.
  185. *
  186. * @param typeInfo Type of the dictionary to create.
  187. */
  188. static MonoObject* createManagedInstance(const ManagedSerializableTypeInfoDictionaryPtr& typeInfo);
  189. protected:
  190. /**
  191. * @brief Retrieves needed Mono types and methods. Should be called
  192. * before performing any operations with the managed object.
  193. */
  194. void initMonoObjects(MonoClass* dictionaryClass);
  195. MonoObject* mManagedInstance;
  196. MonoMethod* mAddMethod;
  197. MonoMethod* mRemoveMethod;
  198. MonoMethod* mTryGetValueMethod;
  199. MonoMethod* mContainsKeyMethod;
  200. MonoMethod* mGetEnumerator;
  201. MonoMethod* mEnumMoveNext;
  202. MonoProperty* mEnumCurrentProp;
  203. MonoProperty* mKeyProp;
  204. MonoProperty* mValueProp;
  205. ManagedSerializableTypeInfoDictionaryPtr mDictionaryTypeInfo;
  206. CachedEntriesMap mCachedEntries;
  207. /************************************************************************/
  208. /* RTTI */
  209. /************************************************************************/
  210. /**
  211. * @brief Creates an empty and uninitialized object used for serialization purposes.
  212. */
  213. static ManagedSerializableDictionaryPtr createEmpty();
  214. public:
  215. friend class ManagedSerializableDictionaryRTTI;
  216. static RTTITypeBase* getRTTIStatic();
  217. virtual RTTITypeBase* getRTTI() const override;
  218. };
  219. }