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