[protobuf] Complex hierarchy test fails with No suitable Default Object encoding found error

108 views
Skip to first unread message

rboarman

unread,
Apr 17, 2010, 6:47:16 PM4/17/10
to Protocol Buffers
Hello,

I am new to this project and so far I am very impressed. My simple
tests went smoothly. However, I have a more complex case that does not
work yet. Perhaps someone can point me in the right direction? I am
using the latest download from the site (1.0.0.280).

When I try to serialize my hierarchy, shown below, I get an error of
“No suitable Default Object encoding found.”

What I am doing wrong eludes me.

Thank you in advance.

Rick


namespace EntityTest1
{
#region Dto objects
[ProtoContract]
[ProtoInclude(10000, typeof(ComplexPropertyDTO<object>))]
public abstract class DynamicPropertyDTO<T>
{
}

[ProtoContract]
[ProtoInclude(10001, typeof(ComponentDTO))]
public class ComplexPropertyDTO<T> : DynamicPropertyDTO<T>
{
[ProtoMember(1)]
public Dictionary<string, object> Properties { get; set; }

public ComplexPropertyDTO()
{
this.Properties = new Dictionary<string, object>();
}
}

[ProtoContract]
[ProtoInclude(10002, typeof(EntityDTO))]
public class ComponentContainerDTO
{
[ProtoMember(2)]
public Dictionary<string, ComponentDTO> Components { get;
set; }

public ComponentContainerDTO()
{
this.Components = new Dictionary<string, ComponentDTO>();
}
}

[ProtoContract]
public class EntityDTO : ComponentContainerDTO
{
[ProtoMember(3)]
public int Id { get; set; }

}

[ProtoContract]
[ProtoInclude(10003, typeof(HealthDTO))]
[ProtoInclude(10004, typeof(PhysicalLocationDTO))]
public class ComponentDTO : ComplexPropertyDTO<object>
{
[ProtoMember(4)]
public EntityDTO Owner { get; set; }
[ProtoMember(5)]
public int Id { get; set; }
[ProtoMember(6)]
public string Name { get; set; }

}

[ProtoContract]
public class HealthDTO : ComponentDTO
{
[ProtoMember(7)]
public decimal CurrentHealth { get; set; }

}

[ProtoContract]
public class PhysicalLocationDTO : ComponentDTO
{
[ProtoMember(8)]
public Point2D Location { get; set; }
}

public struct Point2D
{
public decimal X;
public decimal Y;

public Point2D(decimal x, decimal y)
{
X = x;
Y = y;
}
}
#endregion


class Program
{
static void Main(string[] args)
{
var entity = new EntityDTO() { Id = 1 };
var healthComponent = new HealthDTO() { CurrentHealth =
100, Owner = entity, Name = "Health", Id = 2 };
entity.Components.Add("1", healthComponent);
var locationComponent = new PhysicalLocationDTO()
{ Location = new Point2D() { X = 1, Y = 2 }, Owner = entity, Name =
"PhysicalLocation", Id = 3 };
entity.Components.Add("2", locationComponent);

// Test 1 - simple case, EntityDTO only
var memstream = new MemoryStream();
Serializer.Serialize(memstream, new EntityDTO() { Id =
1 });
var result = Serializer.Deserialize<EntityDTO>(memstream);

Debug.Assert(result.GetType() == typeof(EntityDTO));
Debug.Assert(result.Id == 1);

// Test 2 - Entity and attached components
var memstream2 = new MemoryStream();
Serializer.Serialize(memstream2, new EntityDTO());
var result2 =
Serializer.Deserialize<EntityDTO>(memstream2);

Debug.Assert(result2.Components.Count == 2);
Debug.Assert(result2.Components.Last().Value.Name ==
"PhysicalLocation");
Debug.Assert(result2.Components.First().Value.GetType() ==
typeof(HealthDTO));
Debug.Assert(result2.Components.Last().Value.GetType() ==
typeof(PhysicalLocationDTO));
}
}
}


--
You received this message because you are subscribed to the Google Groups "Protocol Buffers" group.
To post to this group, send email to prot...@googlegroups.com.
To unsubscribe from this group, send email to protobuf+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/protobuf?hl=en.

Marc Gravell

unread,
Apr 18, 2010, 4:25:20 AM4/18/10
to rboarman, Protocol Buffers
I've looked through, and I'm still not sure what ComplexPropertyDTO<T> is trying to do in the "Properties" member. We can't just store "object", as it would have /no clue/ how to encode that. Do you mean Dictionary<string,T> ? This would work for ComplexPropertyDTO<int> etc, but it still wouldn't work for ComplexPropertyDTO<object>. What is the T here meant to be doing?

If you want to support a limited known type of expected types (rather than "object") there are tricks to do that.

Also note that for Point2D, the current build doesn't support custom structs; the re-written unreleased code does, but that isn't available (or rather: isn't fully stable / tested) yet. For now, I would suggest re-exposing the X/Y as private properties on PhysicalLocationDTO (i.e. "Location" isn't a [ProtoMember], but the other 2 private properties are).
Note also that the field numbers only have to be unique within the local type; X / Y could be fields 1 / 2 quite happily.

Marc
Reply all
Reply to author
Forward
0 new messages