Uploaded image for project: 'C# Driver'
  1. C# Driver
  2. CSHARP-3263

BsonSerializer fails to resolve custom serializer. StackOverflow exception when register derived serializers

    • Type: Icon: Bug Bug
    • Resolution: Gone away
    • Priority: Icon: Major - P3 Major - P3
    • None
    • Affects Version/s: 2.11.4
    • Component/s: Serialization
    • Labels:
      None

      It looks like BsonSerializer fails to resolve proper serializer for a member when declared member type doesn't match actual initialized type.

      Observed code flow (might not be exact):

      • BsonMemberMap looks up serializer and calls .Serialize() on found serializer (via extension method I believe).
      • Matched serializer of type ClassSerializerBase<T> calls Serialize() method on base class.
        Serialize() method looks up serializer on actual runtime type (e.g. value.GetType()) which fails to  find serializer for a concrete type.

      If you register concrete type serializer as well, driver fails with StackOverflow exception because of infinite serializer lookup loop.

      Please take a look at minimal repro below.

      class Program
      {
              public class Root
              {
                  // Initialized type doesn't match declared type!!!
                  public IDictionary<int, Node> Nodes { get; set; } 
                     = new Dictionary<int, Node>();
              }        
      
              public class Node
              { 
                  public string Name { get; set; }
              }        
      
              static void Main(string[] args)
              {
                  BsonSerializer.RegisterSerializer(typeof(IDictionary<int, Node>),
                      GetInt32Serializer<Node>());            
      
                  var root = new Root();
                  root.Nodes.Add(0, new Node { Name = "Test" }); 
      
                  using (var stringWriter = new StringWriter())
                  {
                      using (var writer = new JsonWriter(stringWriter))
                      {
                          BsonSerializer.Serialize(writer, root);                     
                          Console.WriteLine("Valid Root: {0}", stringWriter.ToString());
                      }
                  }            
                  Console.ReadKey();
              }   
      
              private static IBsonSerializer GetInt32Serializer<TValue>()
              {
                  return new DictionaryInterfaceImplementerSerializer<IDictionary<int, TValue>, int, TValue>(
                      DictionaryRepresentation.Document,
                      new Int32Serializer(BsonType.String),
                      BsonSerializer.SerializerRegistry.GetSerializer<TValue>());
              }
          }
      

            Assignee:
            james.kovacs@mongodb.com James Kovacs
            Reporter:
            notyourhacker@gmail.com Eduard Muradov
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated:
              Resolved: