Перечислитель Dictionary<string, string> перестает предоставлять интерфейс в середине приложения на некоторых устройствах Android в Unity3D

У нас возникла проблема в Unity3D с использованием C# и JsonFX на некоторых устройствах Android (Nexus 10, Galaxy Note 3 (SM-N9005, SM-N9000Q), Galaxy Tab, S4 (SGH-I337, SGH-M919, GT-I9505) Galaxy Note 10.1 (SM-P600, SM-P601), HTC One).

В начале нашего приложения любой словарь, сериализованный с использованием JsonFX, будет правильно генерировать строку, но в какой-то момент прервется, и с этого момента возникнет исключение JsonSerializationException со следующим сообщением:

Error JsonSerializationException: Types which implement Generic IDictionary<TKey, TValue> must have an IEnumerator which implements IDictionaryEnumerator. (System.Collections.Generic.Dictionary`2[System.String,System.String])

После исследования мы обнаружили, что перед каким-то неизвестным событием следующий код (который является упрощением потока словаря JsonFX)...

var myDictionary = new Dictionary<string, string> {
    { "key1", "value1" },
    { "key2", "value2" },
};
IEnumerator enumerator = ((IEnumerable)((IDictionary)myDictionary)).GetEnumerator();
IDictionaryEnumerator dictionaryEnumerator = enumerator as IDictionaryEnumerator;

... успешно получает словарный перечислитель типа:

System.Collections.Generic.Dictionary`2+Enumerator[[System.String, mscorlib, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.String, mscorlib, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], Dict Enumerator Path 1 = System.Collections.Generic.Dictionary`2+Enumerator[[System.String, mscorlib, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.String, mscorlib, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]

Однажды сломанный, он не может получить перечислитель словаря, потому что возвращаемый перечислитель имеет тип:

System.Collections.Generic.Dictionary`2+KeyCollection[System.String,System.String]

Интересно, что мы попытались создать словарь в начале и повторно протестировать один и тот же экземпляр в нашем игровом процессе, и даже в этом случае он перестает быть сериализуемым после возникновения ошибки.

Примечательно, что это только разрывы для Dictionary - мы выполняем те же тесты с Dictionary, и они продолжают возвращать ожидаемые типы перечислителей. Несмотря на замусоренные тесты и ведение журнала в течение всего игрового процесса, мы не смогли точно определить, где это происходит, так как кажется, что он разрывается между обновлениями сопрограммы.

Мы пытались выгрузить загруженные сборки до и после ошибки, чтобы попытаться поймать версию, изменяющую зависимость, но различий нет.

Эта проблема была вызвана невинным изменением данных, улучшающим нашу поддержку японских символов, поэтому мы подозреваем, что оно выявило существующую проблему.

Мы тривиально решаем проблему, исправляя синтаксический анализ словаря библиотеки Json для поддержки этого нового случая, но мы больше беспокоимся о том, что вызывает эту основную проблему, и о том, какие другие проблемы это может вызывать, которые мы еще не заметили.

Кто-нибудь видел подобные проблемы в том, как изменилось поведение словаря или других классов коллекций, как это, или имел предложения относительно того, как мы можем далее отследить, что вызывает проблему?

1 ответ

Есть много проблем, когда дело доходит до IEnumerator с MonoBehaviour. Я арендовал 10 из них за всю свою карьеру в нашей компании.

Это либо выбросит вас, либо исключение объекта. Система. бла бла бла. Но дело в том, что класс MonoBehaviour. Не имеет функции Add для многих своих классов. Вот почему вы получаете эту ошибку.

Первая помощь, которую мы сделали, - это разделение класса с помощью класса IEnumerator, который наследуется от MonoBehaviour.

Если MonoBehaviour создает экземпляр класса с помощью IEnumerator. Вы обязаны иметь эту проблему.

Прежде чем вы сможете проверить, является ли это реальной проблемой. Попробуйте не поминать MonoBehaviour, и вы увидите, что в IEnumerator нет ошибок. Конечно, у вас будет ошибка об GameObject и тому подобное. Но это только для того, чтобы понять проблему.

Далее, поскольку IEnumerator представляет собой проблему для MonoBehaviour или List,Dictionary или любого GenericType, для которого есть вызовы Add.

Мы решили сделать его массивом. Особенно в десериализации XML и вызовах jSon.

Этот ответ является лишь продолжением того, что вызывает проблему, но чтобы решить вашу проблему. Вам также нужно избегать десериализации IEnumerator из класса MonoBehaviour Inheritance. Или рассмотрите возможность использования массива, в котором нет вызовов Add().

Другие вопросы по тегам