BsManagedSerializableDictionary.h 9.9 KB

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