Hans Kapitein
Hans Kapitein

Reputation: 174

'NotSupportedException: Type cannot be represented as a default value' after updating protobuf-net

After updating to the latest version of protobuf-net (2.4.0) things did not work anymore:

System.InvalidOperationException: It was not possible to prepare a serializer for: QueryContainer

Everything worked fine with version 2.0.0.668 for years, and seems to work with version 2.2.1, but version 2.3.0 and newer result in this issue.

What has changed or what have I never been doing right? :-) I've constructed a small repro, which results in:

It was not possible to prepare a serializer for: ProtoRepro.Program+QueryContainer InnerException: Type cannot be represented as a default value: System.Collections.Generic.KeyValuePair`2[[ProtoRepro.Program+Query, ProtoRepro, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null],[System.Double, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]

using ProtoBuf;
using ProtoBuf.Meta;
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;

namespace ProtoRepro {

  internal class Program {
    private static void Main(string[] args) {
      try {
        RuntimeTypeModel.Default[typeof(QueryContainer)].CompileInPlace();
        // we get here with version 2.2.1 and lower
        Console.WriteLine("Everything is fine!");
      } catch (InvalidOperationException ioex) {
        Console.Write(ioex.ToString());
      } catch (NotSupportedException nsex) {
        Console.Write(nsex.ToString());
      }
    }

    [Serializable, ProtoContract]
    public class QueryContainer {
      private QueryContainer() { }
      [ProtoMember(1, OverwriteList = true)]
      public Dictionary<string, KeyValuePair<Query, double>> QueryAndWeightPerVariable { get; protected set; }
    }

    [Serializable, ProtoContract]
    public class Query {
      [ProtoMember(1)]
      public QueryValue QueryValue { get; set; }
      protected Query() { }
      public Query(QueryValue queryValue) {
        QueryValue = queryValue;
      }
    }

    [Serializable, ProtoContract]
    public class QueryValue {
      [ProtoMember(1)]
      public object Value { get; set; }
      protected QueryValue() { }
      public QueryValue(object value) {
        Value = value;
      }
    }
  }
}

Upvotes: 2

Views: 219

Answers (1)

Marc Gravell
Marc Gravell

Reputation: 1063824

I'm going to have to set up a local test to get to the bottom of it, but there's a good chance that the change here was to do with the "map" behavior. As such you could try adding

[ProtoMap(DisableMap = true)]

to the dictionary member. I apologise if this is a guess (especially if I'm wrong!), but digging into it will have to wait until I have a moment. It may be useful to log it as an issue on GitHub, too.

Upvotes: 2

Related Questions