Search code examples
c#genericsserializable

Create Method for instance of Class


I have have a generic class for a dictionary in c#, however I would like to have added functionality for OnBeforeSerialize() for the different instances/types of the dictionary.

I have three types:

SerializableDictionary<Guid, RoomData>
SerializableDictionary<Guid, AssetData>
SerializableDictionary<Guid, SegData>

I need to add this fuctionality to OnBeforeSerialize to run for each dictionary value:

for RoomData:

    public void GuidToString() {
        roomData.guid = guid.ToString();
        roomData.assetGuidList.Clear();
        roomData.assetGuidList=assetGuidList.Select(g => g.ToString()).ToList();
    }

For AssetData:

public void GuidToString() {
    assetData.guid = guid.ToString();
    assetData.segGuidArray=segGuidArray.Select(g => g.ToString()).ToArray();
    assetData.roomGuid = roomGuid.ToString();
}

For SegData:

public void GuidToString() {
    segData.guid = guid.ToString();
    if (door != null) {
        segData.returnWallGuid = door.returnWall.guid.ToString();
    }
}

How do I ensure that the relevant GuidToString functionality is run with the corresponding types of SerializableDictionary? Thanks y'all

-Rik

Here is the class:

 [Serializable]
 public class SerializableDictionary<TKey, TValue> : Dictionary<TKey, TValue>, ISerializationCallbackReceiver
 {
     [SerializeField]
     private List<TKey> keys = new List<TKey>();

     [SerializeField]
     private List<TValue> values = new List<TValue>();

     // save the dictionary to lists
     public void OnBeforeSerialize()
     {
         keys.Clear();
         values.Clear();
         foreach(KeyValuePair<TKey, TValue> pair in this)
         {
             keys.Add(pair.Key);
             values.Add(pair.Value);
         }
     }

     // load dictionary from lists
     public void OnAfterDeserialize()
     {
         this.Clear();

         if(keys.Count != values.Count)
             throw new System.Exception(string.Format("there are {0} keys and {1} values after deserialization. Make sure that both key and value types are serializable."));

         for(int i = 0; i < keys.Count; i++)
             this.Add(keys[i], values[i]);
     }
 }

Solution

  • Create an interface that has a GuidToString method:

    interface IGuidToStringable {
        void GuidToString();
    }
    

    Have RoomData, AssetData and SegData all implement the interface.

    Constrain TValue to be an implementer of IGuidToStringable:

    public class SerializableDictionary<TKey, TValue> : Dictionary<TKey, TValue>, ISerializationCallbackReceiver where TValue : IGuidToStringable
    

    Now you can call GuidToString:

     public void OnBeforeSerialize()
     {
         keys.Clear();
         values.Clear();
         foreach(KeyValuePair<TKey, TValue> pair in this)
         {
             pair.Value.GuidToString();
             keys.Add(pair.Key);
             values.Add(pair.Value);
         }
     }
    

    I see that GuidToString does not return anything, but its name suggests that it does return a string. Have you considered renaming it?