I have a class like this:
public class Foo
{
public IBar {get;set;}
//tons of other properties
}
public interface IBar
{
//whatever
}
The class is used for binary serialization (standard use of BinaryFormatter). An implementation of IBar is marked with [Serializable] so everything works.
Now I want not to serialize Bar and preserve backwards compatibility (it was not referenced in the code anyway).
NonSerialized attribute seems to be enough. However it can be applied only to fields, not to automatic properties. So I tried this:
public class Foo
{
private IBar _bar;
[NonSerializable]
public IBar Bar
{
get { return _bar; }
set { _bar = value; }
}
}
Suprisingly it works well - I can both deserialize old Foos and the new ones.
My question is: how can it possibly work if these are the fields that are serialized and the automatic property's backing field is likely to have some non-C# characters in its name?
In other words:
Old Foo's IBar field name (my guess): k__BackingField
New Foo's IBar field name: _bar
Obviously they don't match, so how BinaryFormatter overcomes this?
I think there is something strange in your example. BinaryFormatter shouldn't be able to handle this (as far as I know, unless this is changed in 4.5 which I doubt), which is why it is quite dangerous to use if backwards compatibility is necessary. Are you sure the value is serialized from the old version and deserialized to the new version? Can you verify that the deserialized data matches, and aren't null?
For a complete example of a program that verifies that it does not work, see here.
http://www.infragistics.com/community/blogs/josh_smith/archive/2008/02/05/automatic-properties-and-the-binaryformatter.aspx
You will not see any exceptions, but the old value from the field named xyz__backingfield will be lost, and replaced in the new class by a default value.
If you want to be backwards compatible, avoid using automatic properties, or you will be in a world of trouble very soon. In fact it doesn't really matter, since the BinaryFormatter in default (automatic) mode is only really useful if you want to serialize objects and deserialize them again in the same application, for example for copy & paste or a similar operation. In that case you have no versioning issues since it will be the same code doing both the serialization and deserialization.
To make serialization backwards compatible without losing your mind, make sure you have full control of the schema. Good examples of serializers where you have a decent chance of staying out of trouble are DataContractSerializer, Json.NET or Protocol buffers (for example protobuf-net).
As a last possibility you can implement ISerializable and use the dictionary storage of BinaryFormatter, but then you have all the drawbacks of hand-rolling your serialization anyway.
On a sidenote if you want to apply attributes to a backing field try [field:AttriuteType] which is useful to mark backing fields of events as non serialized for example .
Related
Though I'm of course familiar with auto-properties, I just ran across this at work, which seems to be a distinctly different beast:
public SomeType SomeProp
{
get
{
return someField;
}
set
{
}
}
I was surprised it even compiled, and I imagine it must be a bug: the property seems to allow setting, but doing so does absolutely nothing.
Is there a use for this construct? Is it like those "Close Door" buttons in elevators that don't do anything, but make the user feel good?
Why would you expect it not to compile? The setter is just a void method with a single parameter, effectively. You can write broken methods perfectly easily without expecting the compiler to notice - and the same is true of properties.
I can't easily imagine any case where this would be deliberate, however, other than for "partial" implementations - e.g. to demonstrate language features, or if you're testing something that does set a property, but you don't care what the test sets it to. (I'd personally still usually at least record that the property had been set.)
You often see this when a result needs to be serialized in a web service or using an XML or binary serializer.
It's lazy and sloppy, but it happens often. This leaves the object with the "appearance" that the property is settable. If it's done to implement an interface and allow compilation, then the developer who did it needs to be beaten liberally about the head and shoulders with a blunt object, as he just broke the interface. If there is a valid reason that it can't be implemented, then the developer needs to kick it back up to the architect for review. You don't just leave empty stubbed methods behind when implementing an interface. If you don't have a technique defined for implementation at the moment, then at least throw a new NotImplementedException so the unit tests will catch it.
As far as serialization: ReadOnly properties don't get included in regular serialization, and that can leave the property unavailable to a web service client. (ref: Read-Only Properties Cannot Be Exposed by XML Web Services.) This is one of the reasons we should all be moving to WCF and DataContracts. If you accept this class as an input type for a method through WCF, then again retrieve the blunt object.
This doesn't seem useful by itself but consider an interface that required classes to have a SomeProp and you need to implement this interface in your class but have SomeProp only readable and not writeable.
public interface IQuestion
{
public int AnwserToLife { get; set; } //leave out 'set' for read-only
}
public class HitchHiker : IQuestion
{
public int AnwserToLife
{
get
{
return 42;
}
set
{
//never changes
}
}
}
There are a few use cases, where this would be a necessary workaround, some of which I have already encountered "in the wild".
E.g.: The property is a remains from old times, no longer of use, but some other part of the app has never been updated (Source lost? Third party?) and insists on setting the property. I have seen that in old code, that required plugins to set a isDirty property after updating some dataset, when the implementation changed to observe the dataset on itself, the isDirty property became useless, but couldn't be put away, because other code still wants to set it.
I would recommend avoiding this kind of programming. It compiles, because there is no reason it shouldn't, but if the interface requires you to implement a setter method, then there are two options:
Either the setter is redundant and the property should be made read-only, or
There exists a part of your code which will set this value and falsely assume that it worked.
we're using wpf, and would like to serialize a complex object -- a view model.
Using binary formatter, I can just add an attribute [Serializable], and it would automatically work for the entire class, recursively.
Do we have something similar in protobuf?
Also, where is the documentation?
I learned about protoinclude, and protomembers, but these are complex objects that may change.
We want to use protobuf because it is compact, fast, and portable. But I don't rule out other options, if it accomplishes the same goals, more or less, and is easy to use.
Please answer or suggest options. Thank you
BinaryFormatter manages this by including the field name in the output, which is both verbose and brittle (for example, it won't withstand changing something from a field+property to an automatically implemented property).
If you want to do something similar in protobuf-net, you can use "ImplicitFields", however, note that this assigns an integer key to each member alphabetically, so is only suitable if your model is totally fixed as a contract and will not add/rename members as this will break the contract (meaning: you can't deserialize existing data correctly). For example:
[ProtoContract(ImplicitFields = ImplicitFields.AllPublic)]
public class Foo {...} // all public fields and properties are serialized,
// similar to XmlSerializer
[ProtoContract(ImplicitFields = ImplicitFields.AllFields)]
public class Bar {...} // all fields (not properties; public or private)
// are serialized, similar to BinaryFormatter
If your contract is not totally fixed, it would be preferable to explicitly assign a key to each serialized member, which can be done in a great many ways. The simplest being:
[ProtoContract]
public class Foo {
[ProtoMember(1)]
public int A {get;set;}
...
}
So I've been studying the use of various Serializers in the .NET Framework and while trying to experiment on preventing certain objects in a class from being serialized I was thrusted back to some very basic programming questions that I "thought" I knew. Given this example:
public class Example
{
public string examName;
[XmlIgnore]
public int exampleNumber;
public Example()
{ }
[XmlIgnore]
public int ExampleNumberTwo { get; set; }
}
I can create an instance of this class and using the XMLSerializer can output the content of this class in XML format. The [XmlIgnore] attribute actually does what I'd expected; it prevents the serialization of the referenced items.
So venturing further I replaced the [XmlIgnore] declaration for "exampleNumber" with [NonSerializable] expecting the similar results but the output did not change. After searching through resources, it was stated that the [NonSerializable] attribute should only be used on fields and [XmlIgnore] attributes should be used on properties.
Yet another post stated that the [NonSerializable] attribute has no effect when using the XMLSerializer but will produce the expected results when using the SOAP or BinaryFormatter. So I'm lost on the concept at this point.
But this brought me to the basic question, what defines a field vs. a property? I know its a basic question and I've even viewed other discussions here but the degree of clarity I am looking for still wasn't really clear.
I can use the [XmlIgnore] attribute on the property (ExampleNumberTwo) or the variable (exampleNumber) so the statement that it can ONLY be used on Properties doesn't seem correct.
But then again, I have always referred to the objects in my example such as (examName) and (exampleNumber) as being member variables. So what exactly is the signature of a "Field"
Can anyone shed some light on this?
The MSDN documentation supports the idea that [NonSerialized] only gives the expected results with the binary and SOAP serializers:
When using the BinaryFormatter or SoapFormatter classes to serialize
an object, use the NonSerializedAttribute attribute to prevent a field
from being serialized. For example, you can use this attribute to
prevent the serialization of sensitive data.
The target objects for the NonSerializedAttribute attribute are public
and private fields of a serializable class. By default, classes are
not serializable unless they are marked with SerializableAttribute.
During the serialization process all the public and private fields of
a class are serialized by default. Fields marked with
NonSerializedAttribute are excluded during serialization. If you are
using the XmlSerializer class to serialize an object, use the
XmlIgnoreAttribute class to get the same functionality. Alternatively,
implement the ISerializable interface to explicitly control the
serialization process. Note that classes that implement ISerializable
must still be marked with SerializableAttribute.
In terms of "field" vs. "property", fields are straight data variables contained by a class. Properties are actually specially named methods on the class (get_PropName() and set_PropName()). In your code, the compiler allows you to use properties the same way you would use a field, and then inserts the appropriate get/set call for you.
Oftentimes, properties will be simple wrappers around a field:
private int myField;
public int MyProperty
{
get { return myField; }
set { myField = value; }
}
But they don't have to be:
public int TodaysDate
{
get { return DateTime.Today; }
}
In general, you want all your fields to be private, since they're supposed to be implementation details. Any simple data that you'd like to expose should be done via a property, since you can easily surround the data access with (changeable) logic.
In C#, the short answer is that properties have get and/or set methods, while fields do not. VB.NET makes it a little more evident by requiring the "Property" qualifier to be used to differentiate one.
With C#, you can just append " { get; set; }" to the end of a field's definition and it's now a property.
Where this really comes into play is in reflection. Fields and Properties are segregated from one another into different enumerable collections.
This answer to What are the differences between the XmlSerializer and BinaryFormatter will help you get started in the right direction.
This cannot be done in C#. Any way to do it?
...
laugh, in case my little pun wasn't understood, what I mean is: how can I mark a property in C# as NonSerialized? Of course, when the property contains logic, it's natural to be unable to do it, but Auto-Properties are serializable, and, as such, I would expect to have some way to allow me to prevent their serialization.
[NonSerialized]
public string MyProperty { get; set; }
Is an error
[XmlIgnore]
public string MyProperty { get; set; }
Is not an error
NonSerialized Indicates that a field of a serializable class should not be serialized.
XmlIgnore Instructs the Serialize method of the XmlSerializer not to serialize the public field or public read/write property value
so, if you ask
I would expect to have some way to allow me to prevent their serialization.
the answer yes, if you're using XmlSerializer
For events, you can use [field:NonSerialized], but for auto-properties this does not work. It seems like it would be a very logical way to handle auto-properties as well, but for some reason it doesn't seem to have been implemented.
Edit * :
Auto Implemented Properties are backed by an anonymous field which you don't really have access to, attributes are designed to be controlled by a reflection based mechanism. These fields cannot be referenced by the reflection mechanism (because they are anonymous). This compiler feature would require a lot of changes to the generation of auto-properties... It would also require that the compiler treat auto-properties as fields for the purpose of marking field attributes onto them.
To answer the more fundamental part of the question - your point was that Auto-Properties are serialized and so there should be a way to control their serialization. You're right - but auto properties are meant as a shorthand and were never designed to give you the full flexibility, but rather to allow you to easily extend their functionality the "long" way if you ever needed it.
I added the more details answer from my comments to the body of the answer.
I theory yes, it's possible. In practical nope, not possible.
Serialization classes only works on private fields. When you define a auto property; at behind the scenes compiler automatically generates a private field for it. That means this is a language feature not a .net framework feature.
Also serialization classes are included in redbits, which is any change prohibited due compatibility except bug fixes.
I hope thats helps.
What was said above is right: You can't prevent an auto-implemented property from being serialized by setting an attribute like [NonSerialized]. It just does not work.
But what does work is the [IgnoreDataMember] attribute in case you are working with an WCF [DataContract]. So
[DataContract]
public class MyClass
{
[DataMember]
public string ID { get; set; }
[IgnoreDataMember]
public string MySecret { get; set; }
}
will get serialized under WCF.
Although since WCF is an opt-in technology, you can also just omit the [IgnoreDataMember] and it will work as well. So maybe my comment is a little academical ;-)
You could probably do this with Mono.Cecil, a bytecode manipulation library. Theoretically, you could add custom attributes to the hidden backing field. This is so inconvenient, however, that I don't think it warrants an example.
If you had a large application with your own postprocessor, you might consider creating your own substitute for NonSerializedAttribute that could be applied to properties. The postprocessor could then use Mono.Cecil or similar to apply NonSerializedAttribute to the backing fields. It's quite common for large applications to undergo such postprocessing to save that extra bit of typing.
[NonSerialized] public decimal yourproperty;
(decimal as example.)
Also remember, if you want enable your class to initialize a nonserialized member automatically, use the IDeserializationCallback interface and then implement IDeserializationCallback.OnDeserialization.
In the ProtoBuf-Net implementation, what does the ProtoInclude attribute mean, and what does it do?
An example would be appreciated.
I saw it in this post and I'm not sure what it does. The example was:
[Serializable,
ProtoContract,
ProtoInclude(50, typeof(BeginRequest))]
abstract internal class BaseMessage
{
[ProtoMember(1)]
abstract public UInt16 messageType { get; }
}
[Serializable,
ProtoContract]
internal class BeginRequest : BaseMessage
{
[ProtoMember(1)]
public override UInt16 messageType
{
get { return 1; }
}
}
Also, is there a way to generate such inheritance using the protogen tool?
Sorry, I didn't mean to miss this one - alas, I don't see everything.
Given the specifics in the question, I'm going to assume that you are at least passingly familiar with .proto; correct me if I am wrong.
[ProtoInclude] works a lot like [XmlInclude] for XmlSerializer - or [KnownType] for DataContractSerializer - it allows it to recognise subclasses of a type during (de)serialization. The only additional thing is that it needs a tag (number) to identify each sub-type (that must be unique, and not clash with any of the fields from the parent type).
Re protogen: nope; the underlying spec (by google) makes no provision for inheritance at all, so protogen (via .proto) has no mechanism to express this. protobuf-net provides inheritance support as an extension, but does it in a way that still leaves the messages wire-compatible with the other implementations. At a push, maybe I could add protogen support via the new extension properties in the google spec, but I haven't done this yet.
So; to look at the example; that expresses an inheritance relationship between BaseMessage and BeginRequest; regardless of whether you do:
Serialize<BaseMessage>(...)
Serialize<BeginRequest>(...)
either way, it will start at the base (BaseMessage) and work upwards; which isn't exactly true - it writes the data starting with BeginRequest (so that it knows we have a BeginRequest as early as possible during deserialization). The important thing is that the fields from any parent contract types is included, and the serializer looks at the actual object passed in - not just the type you say it is.
Likewise, during deserilaization, regardless of whether you use:
Deserialize<BaseMessage>(...)
Deserialize<BeginRequest>(...)
you will get the type you actually serialized (presumably a BeginRequest).
Under the bonnet, for compatibility purposes (with the wide protocol buffers specification), this is similar to writing something like (forgive any errors, my .proto is rusty):
message BaseMessage {
optional BeginRequest beginRequest = 50;
optional uint32 messageType = 1;
}
message BeginRequest {
}
(the override probably shouldn't specify [ProtoMember], btw.
Normally, it would write fields in ascending tag order, but to make for efficient deserialization the engine cheekily chooses to write the subclass data first (which is explicitly allowed by the spec) - i.e. it writes something like (you'll have to imagine the binary...):
[tag 50, string][length of sub-message][body of sub-message][tag 1, int][value]
(in this case, the body of the sub-message is empty)
Does that cover it?