dotnet / orleans

Cloud Native application framework for .NET
https://docs.microsoft.com/dotnet/orleans
MIT License
10.09k stars 2.03k forks source link

[3.x] Add support for serializing `ConcurrentDictionary<K, V>` #8184

Open ReubenBond opened 1 year ago

ReubenBond commented 1 year ago

This is a request from an internal team to add support for serializing ConcurrentDictionary<K,V>

Here is untested sample code that we could base support on:

[Serializer(typeof(ConcurrentDictionary<,>))]
public static class ConcurrentDictionarySerializer<K, V>
{
    [CopierMethod]
    public static object DeepCopier(object original, ICopyContext context)
    {
        var dict = (ConcurrentDictionary<K, V>)original;
        if (typeof(K).IsOrleansShallowCopyable() && typeof(V).IsOrleansShallowCopyable())
        {
            return new ConcurrentDictionary<K, V>(dict, dict.Comparer);
        }

        var result = new ConcurrentDictionary<K, V>(dict.Comparer);
        context.RecordCopy(original, result);
        foreach (var pair in dict)
        {
            result[(K)SerializationManager.DeepCopyInner(pair.Key, context)] = (V)SerializationManager.DeepCopyInner(pair.Value, context);
        }

        return result;
    }

    [SerializerMethod]
    public static void Serializer(object untypedInput, ISerializationContext context, Type expected)
    {
        var dict = (ConcurrentDictionary<K, V>)untypedInput;
        SerializationManager.SerializeInner(dict.Comparer.Equals(EqualityComparer<K>.Default) ? null : dict.Comparer,
                                       context, typeof(IEqualityComparer<K>));
        context.StreamWriter.Write(dict.Count);
        foreach (var pair in dict)
        {
            SerializationManager.SerializeInner(pair.Key, context, typeof(K));
            SerializationManager.SerializeInner(pair.Value, context, typeof(V));
        }
    }

    [DeserializerMethod]
    public static object Deserializer(Type expected, IDeserializationContext context)
    {
        var comparer = (IEqualityComparer<K>)SerializationManager.DeserializeInner(typeof(IEqualityComparer<K>), context);
        var count = context.StreamReader.ReadInt();
        var dict = new ConcurrentDictionary<K, V>(comparer);
        context.RecordObject(dict);
        for (var i = 0; i < count; i++)
        {
            var key = (K)SerializationManager.DeserializeInner(typeof(K), context);
            var value = (V)SerializationManager.DeserializeInner(typeof(V), context);
            dict[key] = value;
        }
        return dict;
    }
}

Support can be implemented in BuiltInTypes.cs, along with the other built-in serializers.

imnaseem commented 7 months ago

Could you please provide further details on how I can contribute? This is my first time, and I'd appreciate some guidance.