InvalidCastException when adding new elements to Dictionary<UnityEngine.Color, string> using Odin as source

Issue #397 resolved
Fausto Cheder created an issue

Using latest Odin (2.0.1) as source with Unity 2018.2.1f1

Clicking the + button to add an element to a Dictionary<UnityEngine.Color, string> will result in an InvalidCastException.

Editor only mode is not enabled (because I'm using source version). OS is Windows 10 x64

Looking with the debugger, the type there is EditableKeyValuePair not KeyValuePair and, since there's no conversion between those types, I would expect it to fail.

However, looking at the compiled DLL, it seems to use exactly the same route, but it works normally.

Stack + source is below


[Exception] InvalidCastException: Specified cast is not valid.
Sirenix.OdinInspector.Editor.StrongDictionaryPropertyResolver`3[TDictionary,TKey,TValue].Add()    Assets/Vendor/Sirenix/Sirenix.OdinInspector.Editor/Core/Resolvers/Property Resolvers/StrongDictionaryPropertyResolver.cs:264
262:   protected override void Add(TDictionary collection, object value)
263:   {
-->264:       var pair = (KeyValuePair<TKey, TValue>)value;
265:       collection.Add(pair);
266:       this.HandleAddSetPrefabValueModification(pair.Key);

Sirenix.OdinInspector.Editor.BaseCollectionResolver`1+<>c__DisplayClass16_1[TCollection].<QueueAdd>b__0()    Assets/Vendor/Sirenix/Sirenix.OdinInspector.Editor/Core/Resolvers/Property Resolvers/BaseCollectionResolver.cs:150
148:       {
149:           int capture = i;
-->150:           this.EnqueueChange(() => this.Add((TCollection)this.Property.BaseValueEntry.WeakValues[capture], values[capture]));
151:       }
152:   }

Sirenix.OdinInspector.Editor.BaseCollectionResolver`1[TCollection].ApplyChanges()    Assets/Vendor/Sirenix/Sirenix.OdinInspector.Editor/Core/Resolvers/Property Resolvers/BaseCollectionResolver.cs:78
76:   while (changeQueue.Count > 0)
77:   {
-->78:       changeQueue.Dequeue()();
79:   }

Sirenix.OdinInspector.Editor.PropertyTree`1[T].ApplyChanges()    Assets/Vendor/Sirenix/Sirenix.OdinInspector.Editor/Core/PropertyTree.cs:777
775:   IApplyableResolver resolver = property.ChildResolver as IApplyableResolver;
-->777:   if (resolver != null && resolver.ApplyChanges())
778:   {
779:       changed = true;

InspectorUtilities.EndDrawPropertyTree()    Assets/Vendor/Sirenix/Sirenix.OdinInspector.Editor/Misc/InspectorUtilities.cs:258
256:   bool appliedOdinChanges = false;
-->258:   if (tree.ApplyChanges())
259:   {
260:       appliedOdinChanges = true;

PropertyTree.Draw()    Assets/Vendor/Sirenix/Sirenix.OdinInspector.Editor/Core/PropertyTree.cs:277
275:       InspectorUtilities.BeginDrawPropertyTree(this, applyUndo);
276:       InspectorUtilities.DrawPropertiesInTree(this);
-->277:       InspectorUtilities.EndDrawPropertyTree(this);
278:   }

OdinEditor.DrawTree()    Assets/Vendor/Sirenix/Sirenix.OdinInspector.Editor/Drawers/OdinEditor.cs:95
93:   protected virtual void DrawTree()
94:   {
-->95:       this.Tree.Draw(true);
96:   }

OdinEditor.DrawOdinInspector()    Assets/Vendor/Sirenix/Sirenix.OdinInspector.Editor/Drawers/OdinEditor.cs:232
230:   }
-->232:   this.DrawTree();
234:   NetworkBehaviour networkBehaviour = this.target as NetworkBehaviour;

OdinEditor.OnInspectorGUI()    Assets/Vendor/Sirenix/Sirenix.OdinInspector.Editor/Drawers/OdinEditor.cs:87
85:   public override void OnInspectorGUI()
86:   {
-->87:       this.DrawOdinInspector();
88:   }

Comments (5)

  1. Fausto Cheder reporter

    The same exceptions will occur when trying to remove elements


    [Exception] InvalidCastException: Specified cast is not valid.
    Sirenix.OdinInspector.Editor.StrongDictionaryPropertyResolver`3[TDictionary,TKey,TValue].Remove()    Assets/Vendor/Sirenix/Sirenix.OdinInspector.Editor/Core/Resolvers/Property Resolvers/StrongDictionaryPropertyResolver.cs:271
    269:   protected override void Remove(TDictionary collection, object value)
    270:   {
    -->271:       collection.Remove((KeyValuePair<TKey, TValue>)value);
    272:   }
    
    Sirenix.OdinInspector.Editor.BaseCollectionResolver`1+<>c__DisplayClass18_1[TCollection].<QueueRemove>b__0()    Assets/Vendor/Sirenix/Sirenix.OdinInspector.Editor/Core/Resolvers/Property Resolvers/BaseCollectionResolver.cs:173
    171:       {
    172:           int capture = i;
    -->173:           this.EnqueueChange(() => this.Remove((TCollection)this.Property.BaseValueEntry.WeakValues[capture], values[capture]));
    174:       }
    175:   }
    
    Sirenix.OdinInspector.Editor.BaseCollectionResolver`1[TCollection].ApplyChanges()    Assets/Vendor/Sirenix/Sirenix.OdinInspector.Editor/Core/Resolvers/Property Resolvers/BaseCollectionResolver.cs:78
    76:   while (changeQueue.Count > 0)
    77:   {
    -->78:       changeQueue.Dequeue()();
    79:   }
    
    Sirenix.OdinInspector.Editor.PropertyTree`1[T].ApplyChanges()    Assets/Vendor/Sirenix/Sirenix.OdinInspector.Editor/Core/PropertyTree.cs:777
    775:   IApplyableResolver resolver = property.ChildResolver as IApplyableResolver;
    -->777:   if (resolver != null && resolver.ApplyChanges())
    778:   {
    779:       changed = true;
    
    InspectorUtilities.EndDrawPropertyTree()    Assets/Vendor/Sirenix/Sirenix.OdinInspector.Editor/Misc/InspectorUtilities.cs:258
    256:   bool appliedOdinChanges = false;
    -->258:   if (tree.ApplyChanges())
    259:   {
    260:       appliedOdinChanges = true;
    
    PropertyTree.Draw()    Assets/Vendor/Sirenix/Sirenix.OdinInspector.Editor/Core/PropertyTree.cs:277
    275:       InspectorUtilities.BeginDrawPropertyTree(this, applyUndo);
    276:       InspectorUtilities.DrawPropertiesInTree(this);
    -->277:       InspectorUtilities.EndDrawPropertyTree(this);
    278:   }
    
    OdinEditor.DrawTree()    Assets/Vendor/Sirenix/Sirenix.OdinInspector.Editor/Drawers/OdinEditor.cs:95
    93:   protected virtual void DrawTree()
    94:   {
    -->95:       this.Tree.Draw(true);
    96:   }
    
    OdinEditor.DrawOdinInspector()    Assets/Vendor/Sirenix/Sirenix.OdinInspector.Editor/Drawers/OdinEditor.cs:232
    230:   }
    -->232:   this.DrawTree();
    234:   NetworkBehaviour networkBehaviour = this.target as NetworkBehaviour;
    
    OdinEditor.OnInspectorGUI()    Assets/Vendor/Sirenix/Sirenix.OdinInspector.Editor/Drawers/OdinEditor.cs:87
    85:   public override void OnInspectorGUI()
    86:   {
    -->87:       this.DrawOdinInspector();
    88:   }
    
  2. Tor Esa Vestergaard

    Another user has also reported this, and might be posting some more information here soon. Regardless, I will be taking a closer look at this issue very soon (likely tomorrow), as it indicates that Odin's source code is being compiled differently by Roslyn (which we use to build the dll's) and Unity's own integrated compiler(s).

  3. Tor Esa Vestergaard

    This issue has been resolved, and the fix will ship with Odin 2.1. If you need the fix before that, you know the drill by now :)

  4. Log in to comment