ISerializationCallbackReceiver not working with Prefabs

So I made a normal C# class (only inherits from System.Object) called ItemDrop. It represents an item and the conditions that have to be met for it to be dropped from a mob in my game. It has some easily serializable things and other unrelated methods inside the class that I will omit from the code snippets.

The ItemDrop class also contains a list of Conditions, where Condition is another custom class that I made, that also inherits directly from System.Object. This list of Condition objects is not serializable (Not just because it’s private and not marked as SerializeField) because I use C# class inheritance to extend the Condition class, and Unity’s serialization system does not support class inheritance.

My ItemDrop class implements this interface in the UnityEngine called ISerializationCallbackReceiver, that you can use for custom serialization.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Xml.Linq;

[Serializable]
public class ItemDrop : ISerializationCallbackReceiver {
	//Unable to be serialized normally
	private List<Condition> droppableConditions = new List<Condition>(5);
	
	//Able to be serialized, each string represents one of the Condition objects
	[SerializeField]
	private List<string> conditionXmlStrings = new List<string>(5);

	//Here, I prepare the List of string representations just before the objects get destroyed from serialization.
	public void OnBeforeSerialize() {
		conditionXmlStrings = new List<string>(droppableConditions.Count);
		for (int i = 0; i < droppableConditions.Count; i++) {
			if (droppableConditions *!= null)*

_ conditionXmlStrings.Add(Condition.Save(droppableConditions*).ToString());_
_
else*_
* conditionXmlStrings.Add(null);*
* }*
* }*

* //Here, I reconstruct the Condition objects back from the strings*
* public void OnAfterDeserialize() {*
* droppableConditions = new List(conditionXmlStrings.Count);*
* for (int i = 0; i < conditionXmlStrings.Count; i++) {*
_ droppableConditions.Add(Condition.Parse(XElement.Parse(conditionXmlStrings*)));
}*_

* }*
}
So basically for this, I created a List of strings that could store string representations of my objects (the Conditions), survive through serialization, and then be able to be parsed back into Conditions.
So the List of string representations is initialized and the elements are set in the OnBeforeSerialize() function, then Unity’s serialization happens, and then I try to reconstruct my List of Conditions back again in the OnAfterDeserialize() function.
EDIT: Okay, so what was happening that I didn’t understand was that the Conditions (and even the ItemDrops) were getting reset when entering playmode, which I didn’t want to happen. I found that this was happening because the GameObject that these variables were attached to was connected to a prefab, and it was reverting these all to the prefab’s values!
So when I went in the menu with that GameObject selected, GameObject > Break Prefab Instance, then my changes to that GameObject in the Scene were saved and survived into playmode with the ItemDrops and Conditions properly saving! Is there like a UnityEditor.PrefabUtility method or something I can use to make the editor save that instance’s variations from the prefab? (How can I keep it attached to a prefab, yet keep its variations?)
Let me know if you need more details about any part of this.

I am not really able to peek beyond your code and the way you create ItemDrop;

However, the way I would code it would be:

Notice [System.Serializable] attribute in addition to the usual [SerializeField]

 //=new() so that the instance gets created once, at the very start. 
//Afterwards, new MyItemDrop() constructor will not be used, and 
//will receive the serialized value from past instead
[SerializeField] MyItemDrop myDrop =new MyItemDrop();
    
    
[System.Serializable]//<---notice, we want our custom class to respond to [SerializeField] attribute in the above variable.
class MyItemDrop : ISerializationCallbackReceiver {
    
      //same story as with myDrop variable, gets created once, then loaded each time with saved values. This means - afterwards we will never instantiate here, during the declaration of variable.
     [SerializeField] string List<string> _mySerializableStrings = new List<string>();
     [SerializeField] string List<float> _mySerializableFloats = new List<float>();
    
     //since not serialized, this constructor will be called every time myItemDrop is instantiated:
     private Dictionary<string, float> _unityWontSerializeDic = new 
     Dictionary<string, float>();
    
    
     public void OnBeforeSerialize() {
            //save dictionary's keys into strings, and values into floats. Soon dictionary will be wiped-out
     }
    
     public void OnAfterDeserialize() {
          //create a new dictionary. 
          //Even though we instantiated it during declaration, still create an instance here too. This will save you some headache, since unity sometimes (very rarely) calls OnAfterDeserialize() at weird times
    
           //re-populate your dictionary from the survived lists
       }
}

Unity does this:

  1. sais OK I WILL KILL EVERYTHING
  2. notifies everyone who has ISerializationCallbackReceiver, by triggering their OnBeforeSerialize() function
  3. kills everything that is in the format that can’t be serialized and digests what remains into its c++, like a snake
  4. comes back and plugs everything back
  5. calls OnAfterDeserialize on objects, to give them a chance to reconstruct their complex connections