In my personal projects I’ve been using variations on the same simple code for saving/loadings objects for a decade or so, and have very few problems. The heart of the code is this interface -<p><pre><code> public interface IStashy<K>
{
void Save<T>(T t, K id);
T Load<T>(K id);
IEnumerable<T> LoadAll<T>();
void Delete<T>(K id);
K GetNewId<T>();
}
</code></pre>
And implementations of that are very stable over time. Objects get serialized as json and stored in a folder named after their type.<p>There’s a small number of gotchas, for which I have well known work arounds:<p>- I generally won’t remove a property, but mark it as obsolete and stop using it.<p>- If I’ve added a new Boolean property, I’d tend to name it such that it defaults to false, or if it must default to true, have it stored in a nullable boolean, and if it loads as null (from an older instance of the type), set it to the default.<p>- some convenient types I want to use (as properties) are not serializable, so before saving I’ll copy their data into a serializable type, like an array of key values, then on loading rehydrate that to a dictionary. (I guess this is a harsh performance penalty if you’re doing a lot of it in a game)