Is it possible to (de) serialize private property using protobuf-net in Silverlight?

As we know, Silverlight does not allow private reflection. However, I have public property with a private setter, which I need for serialization (no problem here) and deserialize (cheating).

I know that nothing in the world would make protobuf-net for this property in Silverlight, it should be done from the client type (or assembly, if the property is made internal).

Is there a protobuf-net scheme for Silverlight that allows? I could force the type to implement some specialized protobuf-net interface (e.g. IProtoSerializable).

Thank.

EDIT

I can offer such a scheme:

[ProtoMember(N, SetterMethod = "DeserializePropValue")] public string property Prop { get { return m_prop; } private set { m_prop = value; } } public void DeserializePropValue(ProtoValue<string> value) { m_prop = value.Value; } 

If the ProtoValue type is public, but its constructors are internal, so only the protobuf-net assembly can create instances of this type. And, of course, protobuf-net will not publish a public API for creating ProtoValue objects.

This scheme can only be supported for the Silverlight platform, other platforms will simply invoke a private setter.

What do you think?

EDIT2

I want to note that, of course, you can still get a link to an arbitrary PropValue <T> instance, but this is not accidental, and these are random property rewrites that I want to eliminate. In addition, I want the setter to be non-public, so that it does not appear in the various reflection-based binding mechanisms used in the user interface.

EDIT3

PropValue <T> instances may not be suitable for storage, that is, after the DeserializePropValue method returns, the corresponding PropValue instance will be invalidated. This leaves only one way to offend him, for example:

 [ProtoContract] public class Abusee { [ProtoMember(1, SetterMethod = "DeserializePropValue")] public string property Prop { get; private set; } public void DeserializePropValue(ProtoValue<string> value) { m_prop = value.Value; } } [ProtoContract] public class Abuser { private Abusee m_abusee; public Abuser(Abusee abusee, string newPropValue) { m_abusee = abusee; Dummy = newPropValue; Serializer.DeepClone(this); } [ProtoMember(1, SetterMethod = "DeserializeDummyValue")] public string property Dummy { get; private set; } public void DeserializeDummyValue(ProtoValue<string> value) { m_abusee.DeserializePropValue(value); } } 

Quite a lot of effort to happen by chance. As for intentional abuse, there is no regression. You can always serialize an object, manipulate binary serialization data, and then deserialize it. Regression is only the ease of abuse. However, my goal is to:

  • Error Error Prevention
  • Keep the installer not public.
  • Avoid the surrogate nightmare.
+2
protobuf-net
May 19 '11 at 18:34
source share
2 answers

Interest Ask. There is a concept of "surrogates" in v2, which was developed for immutable objects (and structures) that can be useful - it depends on how complex the object is, how attractive the option is. A second option would be to force the property to demonstrate the immutability of the popsicle. I will illustrate both, but:

  • the immutability of the popsicle in this case is only semi-similar and can easily be stepwise; This option is convenient and can be useful if you just want to prevent accidental damage.
  • true immutability gives you more lasting protection; essentially a surrogate acts like a β€œbuilder”, but which never allows you to mutate an existing instance

Note that surrogates cannot be specified in the attribute at the moment (I could add this later; p) - so I used the runtime model to demonstrate this:

 class Program { static void Main() { var obj = new Popsicle(3, 4); var clone = Serializer.DeepClone(obj); Debug.Assert(clone.Foo == obj.Foo); Debug.Assert(clone.Bar == obj.Bar); var model = TypeModel.Create(); model.Add(typeof(MutableSurrogate), false).Add("Foo", "Bar"); model.Add(typeof(ImmutableType), false).SetSurrogate(typeof(MutableSurrogate)); // note you should re-use models (cache them) - or better: pre-generate a serializer dll var obj2 = new ImmutableType(5, 6); var clone2 = (ImmutableType)model.DeepClone(obj2); Debug.Assert(clone2.Foo == obj2.Foo); Debug.Assert(clone2.Bar == obj2.Bar); } } [ProtoContract] // should also work with DataContract etc public class Popsicle { public Popsicle() { } public Popsicle(int foo, int bar) { Foo = foo; this.bar = bar; } private int isBeingDeserialized; [ProtoBeforeDeserialization] public void BeforeDeserialization() { isBeingDeserialized++; } [ProtoAfterDeserialization] public void AfterDeserialization() { isBeingDeserialized--; } [ProtoMember(1)] public int Foo { get; set; } // fully mutable private int bar; [ProtoMember(2)] public int Bar { get { return bar; } set { if (bar == value) return; if (isBeingDeserialized <= 0) throw new InvalidOperationException(); bar = value; } } } public class ImmutableType { private readonly int foo, bar; public ImmutableType(int foo, int bar) { this.foo = foo; this.bar = bar; } public int Foo { get { return foo; } } public int Bar { get { return bar; } } } public class MutableSurrogate { public static implicit operator ImmutableType(MutableSurrogate surrogate) { return surrogate == null ? null : new ImmutableType(surrogate.Foo, surrogate.Bar); } public static implicit operator MutableSurrogate(ImmutableType surrogate) { return surrogate == null ? null : new MutableSurrogate { Foo = surrogate.Foo, Bar = surrogate.Bar }; } public int Foo { get; set; } public int Bar { get; set; } } 

I currently have nothing like IProtoSerializable . I'm still waiting to find what I really need ... I'm not sure if it is.

+4
May 19 '11 at 19:22
source share

Looks like Jackson - the Java Json serializer solved the immutable class problem pretty well: http://www.cowtowncoder.com/blog/archives/2010/08/entry_409.html

Basically annotated using the factory / constructor method and match its input parameters with immutable / read-only properties.

+1
Feb 04 '12 at 8:11
source share



All Articles