Соблюдайте этот простой код, используя 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);
}
}
Последняя строка завершается с ошибкой.Что я делаю неправильно?Спасибо.
РЕДАКТИРОВАТЬ
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:
РЕДАКТИРОВАТЬ2
Я немного изменил код, чтобы исправить суррогатный код, ноэто не влияет на проблему - она остается.
EDIT3
Я знаю, что command2
и command
содержат объекты в другом порядке.Это приемлемо в моем сценарии.Я ожидал, что command3
будет эквивалентно command2
, но по какой-то причине я получаю это исключение.