BsScriptSerializableDictionary.cpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. #include "BsScriptSerializableDictionary.h"
  2. #include "BsScriptSerializableDictionaryRTTI.h"
  3. #include "BsMonoManager.h"
  4. #include "BsRuntimeScriptObjects.h"
  5. #include "BsScriptSerializableField.h"
  6. #include "BsMonoClass.h"
  7. #include "BsMonoMethod.h"
  8. #include "BsMonoProperty.h"
  9. using namespace CamelotFramework;
  10. namespace BansheeEngine
  11. {
  12. ScriptSerializableDictionary::Enumerator::Enumerator(MonoObject* instance, const ScriptSerializableDictionary* parent)
  13. :mInstance(instance), mParent(parent), mCurrent(nullptr)
  14. { }
  15. ScriptSerializableFieldDataPtr ScriptSerializableDictionary::Enumerator::getKey() const
  16. {
  17. MonoObject* obj = mParent->mKeyProp->get(mCurrent);
  18. if(mono_class_is_valuetype(mono_object_get_class(obj)))
  19. return ScriptSerializableFieldData::create(mParent->mDictionaryTypeInfo->mKeyType, mono_object_unbox(obj));
  20. else
  21. return ScriptSerializableFieldData::create(mParent->mDictionaryTypeInfo->mKeyType, obj);
  22. }
  23. ScriptSerializableFieldDataPtr ScriptSerializableDictionary::Enumerator::getValue() const
  24. {
  25. MonoObject* obj = mParent->mValueProp->get(mCurrent);
  26. if(mono_class_is_valuetype(mono_object_get_class(obj)))
  27. return ScriptSerializableFieldData::create(mParent->mDictionaryTypeInfo->mValueType, mono_object_unbox(obj));
  28. else
  29. return ScriptSerializableFieldData::create(mParent->mDictionaryTypeInfo->mValueType, obj);
  30. }
  31. bool ScriptSerializableDictionary::Enumerator::moveNext()
  32. {
  33. mCurrent = mParent->mEnumMoveNext->invoke(mInstance, nullptr);
  34. return mCurrent != nullptr;
  35. }
  36. ScriptSerializableDictionary::ScriptSerializableDictionary(const ConstructPrivately& dummy)
  37. :mManagedInstance(nullptr), mAddMethod(nullptr), mGetEnumerator(nullptr), mEnumMoveNext(nullptr),
  38. mEnumCurrentProp(nullptr), mKeyProp(nullptr), mValueProp(nullptr)
  39. { }
  40. ScriptSerializableDictionary::ScriptSerializableDictionary(const ConstructPrivately& dummy, const ScriptSerializableTypeInfoDictionaryPtr& typeInfo, MonoObject* managedInstance)
  41. :mDictionaryTypeInfo(typeInfo), mManagedInstance(managedInstance), mAddMethod(nullptr), mGetEnumerator(nullptr), mEnumMoveNext(nullptr),
  42. mEnumCurrentProp(nullptr), mKeyProp(nullptr), mValueProp(nullptr)
  43. {
  44. }
  45. ScriptSerializableDictionaryPtr ScriptSerializableDictionary::create(MonoObject* managedInstance, const ScriptSerializableTypeInfoDictionaryPtr& typeInfo)
  46. {
  47. if(managedInstance == nullptr)
  48. return nullptr;
  49. ::MonoClass* monoClass = mono_object_get_class(managedInstance);
  50. String elementNs = mono_class_get_namespace(monoClass);
  51. String elementTypeName = mono_class_get_name(monoClass);
  52. String fullName = elementNs + "." + elementTypeName;
  53. if(RuntimeScriptObjects::instance().getSystemGenericDictionaryClass()->getFullName() != fullName)
  54. return nullptr;
  55. return cm_shared_ptr<ScriptSerializableDictionary>(ConstructPrivately(), typeInfo, managedInstance);
  56. }
  57. ScriptSerializableDictionaryPtr ScriptSerializableDictionary::createEmpty()
  58. {
  59. return cm_shared_ptr<ScriptSerializableDictionary>(ConstructPrivately());
  60. }
  61. void ScriptSerializableDictionary::serializeManagedInstance()
  62. {
  63. MonoClass* dictionaryClass = MonoManager::instance().findClass(mono_object_get_class(mManagedInstance));
  64. if(dictionaryClass == nullptr)
  65. return;
  66. initMonoObjects(dictionaryClass);
  67. mKeyEntries.clear();
  68. mValueEntries.clear();
  69. Enumerator enumerator = getEnumerator();
  70. while(enumerator.moveNext())
  71. {
  72. mKeyEntries.push_back(enumerator.getKey());
  73. mValueEntries.push_back(enumerator.getValue());
  74. }
  75. }
  76. void ScriptSerializableDictionary::deserializeManagedInstance()
  77. {
  78. if(!mDictionaryTypeInfo->isTypeLoaded())
  79. return;
  80. ::MonoClass* dictionaryMonoClass = mDictionaryTypeInfo->getMonoClass();
  81. MonoClass* dictionaryClass = MonoManager::instance().findClass(dictionaryMonoClass);
  82. if(dictionaryClass == nullptr)
  83. return;
  84. initMonoObjects(dictionaryClass);
  85. mManagedInstance = dictionaryClass->createInstance();
  86. assert(mKeyEntries.size() == mValueEntries.size());
  87. for(UINT32 i = 0; i < (UINT32)mKeyEntries.size(); i++)
  88. {
  89. setFieldData(mKeyEntries[i], mValueEntries[i]);
  90. }
  91. }
  92. void ScriptSerializableDictionary::setFieldData(const ScriptSerializableFieldDataPtr& key, const ScriptSerializableFieldDataPtr& val)
  93. {
  94. void* params[2];
  95. params[0] = key->getValue(mDictionaryTypeInfo->mKeyType);
  96. params[1] = val->getValue(mDictionaryTypeInfo->mValueType);
  97. mAddMethod->invoke(mManagedInstance, params);
  98. }
  99. ScriptSerializableDictionary::Enumerator ScriptSerializableDictionary::getEnumerator() const
  100. {
  101. return Enumerator(mGetEnumerator->invoke(mManagedInstance, nullptr), this);
  102. }
  103. void ScriptSerializableDictionary::initMonoObjects(MonoClass* dictionaryClass)
  104. {
  105. mAddMethod = &dictionaryClass->getMethod("Add", 2);
  106. mGetEnumerator = &dictionaryClass->getMethod("GetEnumerator");
  107. MonoClass* enumeratorClass = mGetEnumerator->getReturnType();
  108. assert(enumeratorClass != nullptr);
  109. mEnumMoveNext = &enumeratorClass->getMethod("MoveNext");
  110. mEnumCurrentProp = &enumeratorClass->getProperty("Current");
  111. MonoClass* keyValuePairClass = mEnumCurrentProp->getReturnType();
  112. assert(keyValuePairClass != nullptr);
  113. mKeyProp = &keyValuePairClass->getProperty("Key");
  114. mValueProp = &keyValuePairClass->getProperty("Value");
  115. }
  116. RTTITypeBase* ScriptSerializableDictionary::getRTTIStatic()
  117. {
  118. return ScriptSerializableDictionaryRTTI::instance();
  119. }
  120. RTTITypeBase* ScriptSerializableDictionary::getRTTI() const
  121. {
  122. return ScriptSerializableDictionary::getRTTIStatic();
  123. }
  124. }