i want to implement a general Memento-Pattern in C#. It is working fine but i use the Serializeable() Attribute to do a deep copy of a object. My implementation using generics so if someone use it he has to give his class as type.
Now the class from user must have the Attribute Serializeable() too. Are there any limitations for a class which using Serializeable()?
In fact:
Are there any performance problems?
Is it possible to use an interface?
Is it possible to use inerhitence?
Is it possible to use Auto-Properties?
I dont know how the Attribute works and so iam a bit scary of using this in such a global way.
regards
for small models that you are cloning in memory, not usually
irrelevent; when using [Serializable] you are typically using BinaryFormatter - which looks at the objects themselves; it doesn't matter what interfaces they implement - the interfaces are not used
yes, for the same reason - but all types in the model must be [Serializable]
yes, for the same reason; note : the default BinaryFormatter implementation is looking at fields - it won't even touch the properties
Personally, I try to advise against BinaryFormatter, but this is perhaps not an unreasonable use. However! Be careful that it is easy to suck extra objects into the model accidentally, must commonly through events. Note that it is a good idea to mark all events as non-serialized:
[field:NonSerialized]
public event EventHandler Something;
(or apply to the field directly if using explicit add/remove accessors)
Note also that any members like:
public object Tag {get;set;} // caller-defined
should also probably be [field:NonSerialized].
Personally, I'd prefer a different serializer, but: this will often work. I will say, though: try to avoid persisting the output of BinaryFormatter, as it is hard to guarantee compatibility between revisions of your code.
I dont know how the Attribute works
It does nothing at all except add an IL flag that says "by the way, consider this ok to be serialized"; actually, most serializers don't even look at this flag - but BinaryFormatter is one of the few that do look at this flag. The real code here is BinaryFormatter, which basically does:
have I seen this object before? if so, store the key only
what type is it? is it [Serializable]? store the type info
invent a new reference and store that as the identity
does it have a custom serializer? if so: use that
what fields does it have? access each in turn and store the name/value pair
Related
I am trying to learn to use C# serialization as a way to save objects into files that can be reloaded back into objects.
A plain class like this that I tested
[Serializable()]
public class PlainClass
{
public string Name;
private int Age;
protected decimal Price;
}
Can be directly BinaryFormatter.Serialize() and BinaryFormatter.Deserialize() without errors. (by the way, the private and protected properties also get serialized although the docs say only public)
But the moment it implements ISerialization or inherit some class like Hashtable that implements ISerialization, the you-know-what deserialization constructor is required. The word or concept of "implement" becomes a misnomer because Hashtable does not actually implement that constructor.
Is there a way to fall back to the "auto" Serialization/Deserialzation provided only by the attribute? Or is there an easier way to write info.GetValue() for a hundred properties in a class?
There is a lot of confusion in your post:
by the way, the prive and protected properties also get serialized although the docs say only public)
I suspect you are confusing two different serializers; BinaryFormatter is and always has been documented as field-centric. It doesn't distinguish between public/private, and it never looks at properties: only fields. XmlSerializer, by contrast, only looks at public properties and fields.
The word or concept of "implement" becomes a misnomer because Hashtable does not actually implement that constructor.
Yes it does; it is a protected constructor:
protected Hashtable(SerializationInfo info, StreamingContext context)
{...}
If you inherit Hashtable you can chain to this constructor:
protected YourType(SerializationInfo info, StreamingContext context)
: base(info, context)
{ /* your extra data */ }
Note, however, that you probably shouldn't be using Hashtable much unless you are on .NET 1.1.
Is there a way to fall back to the "auto" Serialization/Deserialzation provided only by the attribute?
No; none.
Or is there an easier way to write info.GetValue() for a hundred properties in a class?
In the case of inherited data, you could chain the base-constructor or switch to encapsulation instead of inheritance - either avoids the need to worry about data other than your own.
Note, however, that I almost always guide against BinaryFormatter - it can be vexing, and is quirky with versioning. For every annoyance with BinaryFormatter, I use protobuf-net (I would, since I wrote it) - this generally makes serialization much more controlled (and more efficient), and includes an ISerializable hook if you really want to use BinaryFormatter (i.e. it can use BinaryFormatter as the wrapper, but with a protobuf-net payload).
Hashtable/Dictionary requires the implementation of the respective methods...
To work around that you would have to implement a separate class to hold the Dictionary data and provide an IList interface instead which in turn need not work on TKeyValuePair but with a separately implemented class with Key/Value (refer to http://blogs.msdn.com/b/adam/archive/2010/09/10/how-to-serialize-a-dictionary-or-hashtable-in-c.aspx)...
As you can see from the start of my explanation - this is nothing you would usually want to do...
There are better serialization solutions out there - see for a very good one http://code.google.com/p/protobuf-net/
Can I rely on the fact that the underlying field to a property named Foo is called "k__BackingField" ?
No, in short.
And for this very reason, auto-properties are pain when used with field-based serializers like BinaryFormatter (I'm sure I might have mentioned that here before ;-p).
See: Obfuscation, serialization and automatically implemented properties for some thoughts on this (and a solution).
That the spec does not specify the backing field's name (with good reason - you shouldn't take a dependency on it).
You should investigate to see whether the Mono compiler does the same thing for example.
Sanity checking that the field had the CompilerGeneratedAttribute applied to it would be a good idea.
Note that explicit interface implementations would come out (currently) as:
<Full.Namespace.To.Interface.IBlah.Foo>k__BackingField
So code which is trying to serialize a specific aspect of a class in this fashion could be mislead.
If you wanted to be really belt and braces about your code you could use a library like mono's Cecil to inspect the get function of the property and determine the field used.
Of course not. That would be a private implementation detail.
And why on Earth would you want to know?
I don't think so. If you need the backing field, use a 'regular' property.
Are there any closed or open source projects for a XML serializer for C# that can serialize for the most part any object without the need to pollute my domain objects with tons of attributes? That will also handle serialization of collections built with the internal generics classes? A bonus would be that it can handle serializing an interface type property. Another bonus would be that it can serialize objects that have read-only properties (or atleast with the get accessor marked internal)
Well, first define "advanced", i.e. what specifically do you need that XmlSerializer doesn't have. In terms of POCO, XmlSerializer has an overloaded ctor that accepts all the attributes you could ever want to add, to avoid having to add them to your object model - but it does still require a public parameterless constructor, and only works on public read/write fields/properties. And you should cache/re-use the serializer if you use this approach.
I'm not aware of any like alternatives, simply because in most cases this is "good enough" - and it is often a mistake to try to brute-force your existing domain object into a DTO. It may be simpler and more maintainable to simply map your domain entities onto a new DTO(s) that are attributed (and have appropriate ctor/properties/etc).
Note that for the ctor/properties issue DataContractSerializer has some answers, but this doesn't have as much fine-grained control over what the xml looks like.
You can allow System.Xml.dll to access your internals by using the InternalsVisibleToAttribute.
Thus serializing internal types and/or internal members. Including internal .ctors.
You can also implement IXmlSerializable on classes to customize their serialization (like the container containing interface references).
You do not have to provide the XML serialization attributes on your classes, but provide them as XmlAttributeOverrides instead.
XmlSerializer is almost always exactly what people want, they just don't know that it is as flexible as it really is.
Is there any way to add Field (or FieldInfo, maybe this is the same) to a class at runtime?
You can't alter a class definition at runtime. However, you can create a new class that inherits from the original class (if it's not sealed) and declares the field. You can do this by emitting the appropriate IL code using System.Reflection.Emit.
No, C# doesn't allow monkey-patching.
You can generate new classes using either CodeDOM or Reflection.Emit, but you can't modify existing ones.
C# does not allow it because all of it's classes are based on Metadata. The CLR (not C#) disallows the adding of fields to metadata at runtime (1). This is the only way that C# would be able to add a field at runitme.
This is unlike dynamic langauges such as IronPython which essentially don't have concrete metadata classes. They have more dynamic structures which can be altereted at runtime. I believe IronPython simply keeps it's members (fields and methods) in what amounts to a hashtable that can be easily altered at runtime.
In C# 3.0, your best resource is to use Reflection.Emit. But this will generate an entirely new class vs. altering an existing one.
(1) There are certain APIs such as the profiling APIs or ENC that allow this but I'm not sure if their capabalities expand to adding fields.
See this question for a simple way to do it in C# 4.0, by casting an ExpandoObject as an IDictionary, which causes the values added to the dictionary to become properties of the object. I demonstrate this in another answer of mine showing that they actually become properties.
However, this is only possible with an instance of ExpandoObject or by sub-classing DynamicObject.
It may also be possible to use with other classes if they implement IDynamicMetaObjectProvider, but I think there is too much work involved to get it to work properly.
Not exactly.
However, you can implement ICustomTypeDescriptor to approximate it, and then just use a hashtable to store the fieldname/value pairs. A lot of the framework which uses reflection asks for ICustomTypeDescriptor first.
Not until C# 4.0 which adds dynamic lookup and is based on the CLR 4.0 which incorporates the DLR, and then it will not strictly be adding to a class, as classes won't be in the picture.
as others already said, this isn't possible. What is the reason for your question? If you need to store some additional data in the class dynamically, then you could probably just use dictionary:
class My {
Dictionary<string, object> data;
public My() { data = new Dictionary<string, object>(); }
}
.. but it really depends on what you actually want to achieve?
Perhaps you could use the Decorator pattern.
In object-oriented programming, the decorator pattern is a design pattern that allows behavior to be added to an individual object, either statically or dynamically, without affecting the behavior of other objects from the same class.
http://www.dofactory.com/Patterns/PatternDecorator.aspx
I have data stored in an instance of a class which has been serialized with the .net BinaryFormatter. I now want to rename one of the fields in the class, but still be able to deserialize the old data.
One option is to implement ISerializable and deserialize all the the fields of the class manually. But this seems like a lot of work, especially if my class has lots of fields and I've only renamed a single field.
Is there a better way?
Craig suggests keeping a copy of the old class for deserialization, and copying values to the new class. I've seen this suggested elsewhere too - what advantage does this have over implementing ISerializable? As far as I can see, copying the class leaves me with 2 almost identical copies of the class plus I still have to copy all the values from the old class to the new class - which seems the same amount of work as implementing ISerializable with an almost duplicate class thrown into mix.
Two answers have mentioned Binders. I've successfully used a SerializationBinder to deserialize a class Bar which was Serialized as class Foo, but that's because the name of the class changed. Does SerializationBinder also help when you've renamed a field - say when int m_Left has been renamed to int m_Right?
Yes, this is the problem with field-based serializers. You can use either a custom Binder, or a "serialization surrogate" to avoid implementing ISerializable, but that is only a case-by-case fix.
I've discussed this topic (in the context of obfuscators, and auto-props) here. My advice is: don't use BinaryFormatter for persistance of data between versions... for that, look at contract-based serializers:
XmlSerializer
DataContractSerializer
or for binary, things like protobuf-net
None of this helps you today, but it might help you design around it in the future.
You could try having the old calss hang around for the sole purpose of rehydration and then just copy over the fields you need to the new class. Still kind of painful but should work.
I used SerializationBinder class for this before
http://msdn.microsoft.com/en-us/library/system.runtime.serialization.serializationbinder.aspx
it can be used for deserialization so you can remap old type to new one.
What if you just change the access modifier on that one property to private, and then have a public property with the new name that just basically wraps the old one. That way you should still be able to deserialize (I THINK) but anyone using this class won't know about the old name. Just a thought...