What is wrong with this use of the protobuf-net surrogate?

Follow this simple code using protobuf-net v2:

  interface IObject { }

  [ProtoContract]
  class Person : IObject
  {
    [ProtoMember(1)]
    public int Id { get; set; }
    [ProtoMember(2)]
    public string Name { get; set; }
    [ProtoMember(3, AsReference = true)]
    public Address Address { get; set; }
  }
  [ProtoContract]
  class Address : IObject
  {
    [ProtoMember(1)]
    public string Line1 { get; set; }
    [ProtoMember(2)]
    public string Line2 { get; set; }
  }

  class Command
  {
    public List<IObject> Objects { get; set; }
  }

  internal interface ICommandSurrogatePiece
  {
    IEnumerable<IObject> Objects { get; set; }
  }

  [ProtoContract]
  class CommandSurrogatePiece<T> : ICommandSurrogatePiece 
      where T : class, IObject
  {
    [ProtoMember(1)]
    public List<T> Objects { get; set; }

    #region ICommandSurrogatePiece Members

    IEnumerable<IObject> ICommandSurrogatePiece.Objects
    {
      get { return Objects; }
      set { Objects = value as List<T> ?? value.Cast<T>().ToList(); }
    }

    #endregion
  }

  [ProtoContract]
  class CommandSurrogate
  {
    public static implicit operator Command(CommandSurrogate surrogate)
    {
      var objects = surrogate.Pieces.SelectMany(c => c.Objects).ToList();
      return new Command { Objects = objects };
    }
    public static implicit operator CommandSurrogate(Command cmd)
    {
      var pieces = cmd.Objects.GroupBy(o => o.GetType(), 
          o => o, CreateCommandSurrogatePiece).ToList();
      return new CommandSurrogate { Pieces = pieces };
    }

    private static ICommandSurrogatePiece CreateCommandSurrogatePiece(
        Type type, IEnumerable<IObject> objects)
    {
      var piece = (ICommandSurrogatePiece)Activator.CreateInstance(
          typeof(CommandSurrogatePiece<>).MakeGenericType(type));
      piece.Objects = objects;
      return piece;
    }

    [ProtoMember(1, DynamicType = true)]
    public List<ICommandSurrogatePiece> Pieces { get; set; }
  }

  class Program
  {
    static void Main()
    {
      var person = new Person { Id = 12345, Name = "Fred", Address = 
          new Address { Line1 = "Flat 1", Line2 = "The Meadows" } };
      var person2 = new Person { Id = 2345, Name = "Fred kaka", Address = 
          new Address { Line1 = "Flat 12", Line2 = "The Meadows kuku" } };
      var address = 
          new Address { Line1 = "Flat 2", Line2 = "The Meadows Double" };
      var address2 = 
          new Address { Line1 = "Flat 2 bubub", 
              Line2 = "The Meadows Double kuku" };

      var model = TypeModel.Create();
      model.Add(typeof(CommandSurrogate), true);
      model.Add(typeof(Command), false).SetSurrogate(typeof(CommandSurrogate));
      var command = new Command { Objects = 
          new List<IObject> { person, address, person2, address2 } };
      var command2 = (Command)(CommandSurrogate)command;
      var command3 = Serializer.DeepClone(command);
    }
  }

The last line fails with an exception. What am I doing wrong? Thank.

EDIT

System.InvalidOperationException occurred
  Message=Type is not expected, and no contract can be inferred: HelloProtoBuf.Command
  Source=protobuf-net
  StackTrace:
       at ProtoBuf.Meta.TypeModel.ThrowUnexpectedType(Type type)
  InnerException: 

EDIT2

I changed the code a bit to fix the surrogate code, but this does not affect the problem - it remains.

EDIT3

I know that command2they commandcontain objects in a different order. This is acceptable in my scenario. I expected it to command3be equivalent command2, but for some reason I get this exception.

+3
source share
1 answer

, , . , , model. API v1 (.. Serializer.blah) RuntimeTypeModel.Default.

Try:

var command3 = (Command)model.DeepClone(command);

, null - :

if (cmd == null) return null;

. , , , , .

+1

All Articles