using IPA.Config.Data; using System; namespace IPA.Config.Stores.Converters { /// /// A for objects normally serialized to config via . /// /// the same type parameter that would be passed into /// public class CustomObjectConverter : ValueConverter where T : class { private interface IImpl { T FromValue(Value value, object parent); Value ToValue(T obj, object parent); } private class Impl : IImpl where U : class, GeneratedStoreImpl.IGeneratedStore, T { private static readonly GeneratedStoreImpl.GeneratedStoreCreator creator = GeneratedStoreImpl.GetCreator(typeof(T)); private static U Create(GeneratedStoreImpl.IGeneratedStore parent) => creator(parent) as U; public T FromValue(Value value, object parent) { // lots of casting here, but it works i promise (probably) (parent can be a non-IGeneratedStore, however it won't necessarily behave then) var obj = Create(parent as GeneratedStoreImpl.IGeneratedStore); obj.Deserialize(value); return obj; } public Value ToValue(T obj, object parent) { if (obj is GeneratedStoreImpl.IGeneratedStore store) return store.Serialize(); else { var newObj = Create(null); newObj.CopyFrom(obj, false); // don't use lock because it won't be used return newObj.Serialize(); } } } private static readonly IImpl impl = (IImpl)Activator.CreateInstance( typeof(Impl<>).MakeGenericType(typeof(T), GeneratedStoreImpl.GetGeneratedType(typeof(T)))); /// /// Deserializes into a with the given . /// /// the to deserialize /// the parent object that will own the deserialized value /// the deserialized value /// public static T Deserialize(Value value, object parent) => impl.FromValue(value, parent); /// /// Serializes into a structure, given . /// /// the object to serialize /// the parent object that owns /// the tree that represents /// public static Value Serialize(T obj, object parent) => impl.ToValue(obj, parent); /// /// Deserializes into a with the given . /// /// the to deserialize /// the parent object that will own the deserialized value /// the deserialized value /// public override T FromValue(Value value, object parent) => impl.FromValue(value, parent); /// /// Serializes into a structure, given . /// /// the object to serialize /// the parent object that owns /// the tree that represents /// public override Value ToValue(T obj, object parent) => impl.ToValue(obj, parent); } }