Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

explore what's required for serialization #32

Open
nadako opened this issue Aug 13, 2024 · 0 comments
Open

explore what's required for serialization #32

nadako opened this issue Aug 13, 2024 · 0 comments

Comments

@nadako
Copy link
Owner

nadako commented Aug 13, 2024

We might need to expose some APIs to provide a way to (de-)serialize State. With Json.NET, it doesn't actually need any changes to the library, here's a quick and dirty implementation of a JsonConverter:

class StateJsonConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        if (objectType.IsGenericType)
        {
            // field type definition for deserialization - the interface directly
            if (objectType.GetGenericTypeDefinition() == typeof(State<>))
            {
                return true;
            }
            
            // run-time object type for serialization - the implementation
            foreach (var iface in objectType.GetInterfaces())
            {
                if (iface.IsGenericType && iface.GetGenericTypeDefinition() == typeof(State<>))
                {
                    return true;
                }
            }
        }
        return false;
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        GetConverter(value.GetType()).WriteJson(writer, value, serializer);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        return GetConverter(objectType).ReadJson(reader, existingValue, serializer);
    }
    
    StateConverter GetConverter(Type stateType)
    {
        // TODO: cache converters
        var rt = typeof(StateConverter<>).MakeGenericType(stateType.GetGenericArguments()[0]);
        return (StateConverter)Activator.CreateInstance(rt, false);
    }
}

abstract class StateConverter
{
    public abstract void WriteJson(JsonWriter writer, object value, JsonSerializer serializer);

    public abstract object ReadJson(JsonReader reader, object existingValue, JsonSerializer serializer);
}

class StateConverter<T> : StateConverter
{
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        WriteJsonInternal(writer, (State<T>)value, serializer);
    }

    public override object ReadJson(JsonReader reader, object existingValue, JsonSerializer serializer)
    {
        return ReadJsonInternal(reader, existingValue, serializer);
    }

    void WriteJsonInternal(JsonWriter writer, State<T> state, JsonSerializer serializer)
    {
        serializer.Serialize(writer, state.Value);
    }

    State<T> ReadJsonInternal(JsonReader reader, object existingValue, JsonSerializer serializer)
    {
        var stateValue = serializer.Deserialize<T>(reader);
        if (existingValue is State<T> existingState)
        {
            existingState.Value = stateValue;
            return existingState;
        }
        return Observable.State(stateValue);
    }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant