2
0

BsScriptSerializableDictionary.cpp 5.8 KB

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