views:

165

answers:

1

I am trying to serialize a ItemTransaction and protobuf-net (r282) is having a problem.

ItemTransaction : IEnumerable<KeyValuePair<Type, IItemCollection>></code>

and ItemCollection is like this:

FooCollection : ItemCollection<Foo>
ItemCollection<T> : BindingList<T>, IItemCollection
IItemCollection : IList<Item>

where T is a derived type of Item. ItemCollection also has a property of type IItemCollection.

I am serializing like this:

IItemCollection itemCol = someService.Blah(...);
...
SerializeWithLengthPrefix<IItemCollection>(stream, itemCol, PrefixStyle.Base128);

My eventual goal is to serialize ItemTransaction, but am snagged with IItemCollection.

Item and it's derived types can be [de]serialized with no issues, see [1], but deserializing an IItemCollection fails (serializing works). ItemCollection has a ItemExpression property and when deserializing protobuf can't create an abstract class. This makes sense to me, but I'm not sure how to get through it.

ItemExpression<T> : ItemExpression, IItemExpression
ItemExpression : Expression

ItemExpression is abstract as is Expression

How do I get this to work properly?

Also, I am concerned that ItemTransaction will fail since the IItemCollections are going to be differing and unknown at compile time (an ItemTransaction will have FooCollection, BarCollection, FlimCollection, FlamCollection, etc).

What am I missing (Marc) ?

[1] http://stackoverflow.com/questions/2276104/protobuf-net-deserializing-across-assembly-boundaries

+1  A: 

I'm not entirely clear on the entire scenario; however Merge can be used to pass a concrete item in (in the case where you want to create an empty concrete instance yourself and let protobuf-net fill in the properties).

If the ItemExpression is decorated with [ProtoInclude(...)] for the expected ItemExpression<T> it should allow deserialization - abstract types are supported just as long as it never finds it needs to create one! See also my answer here which shows this in use.

If you can supply an example that I can use to reproduce the issue I should be able to provide more information.


Based on some off-forum examples, I think I've concluded that this is supported, but:

  • if you just use Deserialize..., the outmost IList<T> derivative will be created by default as List<T>; you can get around this by using Merge instead, passing in a concrete list instance of your choosing to be filled
  • all of Item, Foo, Bar should be marked as contract-types, with appropriate inheritance markers between Item and Foo, and Item and Bar
  • in "v2" (soon) there is more control to manage concrete list types (and item types for untyped lists)
  • there does seem to be a glitch related to list deserialization where the stated item type is not the root type. This looks to have been fixed automatically in "v2", but I need to chase it through (this unfortunately touches on the wrapper "WithLengthPrefix" / list outermost methods, which I'm still working on)
  • in "v2" you can do the whole thing without needing the attributes if you like (although it still needs to be told how at some point)

But yes; it should work. I've e-mailed you a sample, and intend to tidy up the aforementioned outermost methods.

Marc Gravell
@tsupe - "Error 320", "The key you provided for file download was invalid."; you could try e-mailing me directly (see my profile page)
Marc Gravell
Thanks, Marc. I've emailed you.
tsupe
Based on our emails and my investigation, protobuf-net v1 won't meet our needs at the moment and the current schedule and situation does not allow us to use non-production code. Thank you for your help.
tsupe