Click here to Skip to main content
Click here to Skip to main content

XML Serialization of Generic Dictionary, Multidimensional Array, and Inherited Type, with sharpSerializer .NET

By , 9 Nov 2011
 

Table of Contents

Introduction

sharpSerializer is an open source object serializer for .NET Framework, .NET Compact Framework and Silverlight. Its purpose is simple - quick object serialization from A to B, without security considerations. In this article, I'll try to convince you that sharpSerializer can be a lot more than the built-in XMLSerializer and is simpler.

Background

The built-in XmlSerializer has some restrictions concerning object serialization:

  • It cannot serialize multidimensional arrays.
  • It cannot serialize a generic Dictionary<TKey,TValue>.
  • It cannot serialize polymorphic properties (with an inherited value type from the property type) out of the box.
  • It needs the type of the serialized object in its Serialize(...) method.
  • It needs many attributes to define your business objects, e.g.: XmlArrayAttribute, XmlArrayItemAttribute to define the array of inherited types.

sharpSerializer overcomes the above restrictions, and serializes objects with no need to mark your objects with additional attributes and without concerning types being serialized.

Using the Code

Hello World with sharpSerializer

Let's assume we have an object:

public class SomeObject
{
    public int SimpleInt { get; set; }
    public DateTime SimpleDateTime { get; set; }
    public TimeSpan SimpleTimeSpan { get; set; }
    public SimpleEnum SimpleEnum { get; set; }
    public string SimpleString { get; set; }
}

public enum SimpleEnum {One,Two,Three}

We initialize and serialize this object:

// instantiate the object
var obj = new SomeObject(){
                      SimpleDateTime = new DateTime(2010,4,28),
                      SimpleEnum = SimpleEnum.Three,
                      SimpleInt = 42, 
                      SimpleString = "nothing",
                      SimpleTimeSpan = new TimeSpan(1,2,3)};

// instantiate the sharpSerializer
// with standard constructor it serializes to XML
// overloaded constructors activate binary serialization
var serializer = new SharpSerializer();

// serialize
serializer.Serialize(obj, "test.xml");

// deserialize (to check the serialization)
var obj2 = serializer.Deserialize("test.xml");

Notice! You don't need to mark your object with any attribute, nor do you have to give the object type in the Serialize method.

This object serializes to the following XML:

<Complex name="Root" type="SharpSerializerTestApp.SomeObject, SharpSerializerTestApp">
  <Properties>
    <Simple name="SimpleInt" value="42" />
    <Simple name="SimpleDateTime" value="04/28/2010 00:00:00" />
    <Simple name="SimpleTimeSpan" value="01:02:03" />
    <Simple name="SimpleEnum" value="Three" />
    <Simple name="SimpleString" value="nothing" />
  </Properties>
</Complex>

As you can see, the object type was serialized as "TypeName, AssemblyName" and DateTime was serialized as CultureInfo.InvariantCulture. Later, I'll show you how to customize the type name (i.e., as AssemblyQualifiedName) and how to save DateTime and float numbers in your desired format.

Excluding Properties from the Serialization

By default, all properties are serialized, which are public, instance, and not read-only. All properties which are arrays (Type.IsArray==true), or which inherit from IEnumerable, ICollection or IDictionary are also serialized. For performance reasons, fields are not serialized.

  1. To exclude properties in your custom types, you need to mark them with attributes. ExcludeFromSerializationAttribute is supported out of the box.
    public class MyClass
    {
        [ExcludeFromSerialization]
        public int SimpleInt { get; set; }
    }
  2. If your objects are marked with common .NET Attributes such as XmlIgnore, you can add these attributes to the listing AttributesToIgnore.
    // remove default ExcludeFromSerializationAttribute for performance gain
    serializer.PropertyProvider.AttributesToIgnore.Clear(); 
    serializer.PropertyProvider.AttributesToIgnore.Add(typeof(XmlIgnore));

    or using the settings class:

    // for binary mode
    var settings = new SharpSerializerBinarySettings();
    // for xml mode
    var settings = new SharpSerializerXmlSettings(); 
    // remove default ExcludeFromSerializationAttribute for performance gain
    settings.AdvancedSettings.AttributesToIgnore.Clear(); 
    settings.AdvancedSettings.AttributesToIgnore.Add(typeof(XmlIgnore));
  3. To exclude properties of the built in .NET types, or if you cannot extend properties with attributes, you add the type and its property name to the list SharpSerializer.PropertyProvider.PropertiesToIgnore.

    i.e. System.Collections.Generic.List<T> has property Capacity which is irrelevant for the serialization, thus it should be ignored.
    serializer.PropertyProvider.PropertiesToIgnore.Add
    	(typeof(List<string>), "Capacity");

    PropertiesToIgnore can be also accessed from the sharpSerializer settings.

    // create the settings
    var settings = new SharpSerializerBinarySettings(); // for binary mode
    var settings = new SharpSerializerXmlSettings(); // for xml mode
    settings.AdvancedSettings.PropertiesToIgnore.Add(typeof(List), "Capacity");

Customizing the Property List for Serialization

If it is not enough to filter properties with ExcludeFromSerializationAttribute, AttributesToIgnore or PropertiesToIgnore, you can build your CustomPropertyProvider. As a base class, there is PropertyProvider, which has two virtual methods GetAllProperties() and IgnoreProperty(...). They can be overwritten to customize the logic.

serializer.PropertyProvider = new MyCustomPropertyProvider();

Serializing type as AssemblyQualifiedName or as a short type name "TypeName, AssemblyName"

Before SharpSerializer v.2.12, all types were serialized as short type name "TypeName, AssemblyName"; i.e.:

type="System.String, mscorlib"

This was simple to read, output size was small. But it encountered problems during deserialization if working with signed assemblies or their specific versions.

Since SharpSerializer v.2.12 are all types serialized as AssemblyQualifiedName; i.e.:

type="System.String, mscorlib, Version=2.0.0.0, 
      Culture=neutral, PublicKeyToken=b77a5c561934e089"

You can alter the type naming by altering settings of sharpSerializer and setting the properties IncludeAssemblyVersionInTypeName, IncludeCultureInTypeName and IncludePublicKeyTokenInTypeName. As default, these properties are set to true.

var settings = new SharpSerializerXmlSettings();

settings.IncludeAssemblyVersionInTypeName = false;
settings.IncludeCultureInTypeName = false;
settings.IncludePublicKeyTokenInTypeName = false;

var serializer = new SharpSerializer(settings);

Custom Formatting of DateTime and Float Values

By default, all primitive types and DateTime are converted to strings according to CultureInfo.InvariantCulture. If custom formatting or a culture is needed, this can be achieved with the following modification of the settings class:

var settings = new SharpSerializerXmlSettings();
settings.Culture = System.Globalization.CultureInfo.CurrentCulture;
var serializer = new SharpSerializer(settings);

Serialize Data to Other Format as XML

Actually, sharpSerializer can serialize to XML and to its own binary format. However, after injecting it with custom IXmlWriter or IBinaryWriter it can serialize data to other text formats like Json or other encrypted, compressed, optimized, etc. binary streams. Please refer to the project site for details concerning binary serialization.

How Does sharpSerializer Work?

It works in three steps:

Step 1

The PropertyFactory converts an object to the Property. The abstract class Property contains PropertyCollection. PropertyCollection represents the object structure and its data. The following classes inherit from the Property class:

  • SimpleProperty for describing all primitive types and string, DateTime, TimeSpan and all enumerations
  • ComplexProperty for other classes and structures which are not listings
  • ComplexReferenceProperty for referencing a class which was already serialized (it saves space.)
  • SingleDimensionalArrayProperty for single dimensional arrays
  • MultiDimensionalArrayProperty for multidimensional arrays
  • CollectionProperty for listings which inherit from ICollection but not from IDictionary
  • DictionaryProperty for listings which inherit from IDictionary
  • NullProperty for all objects/strings which are null (there is a need to make a notice that they are null)

Step 2

Property is serialized by XmlPropertySerializer. In which format it is serialized depends on the used writer.

Step 3

For XML serialization, DefaultXmlWriter is responsible. But as a sink can be used any writer, which implements IXmlWriter. In this way, you can write your own writers which serialize data to other formats like Json.

During deserialization, the process is inversed. An instance of IXmlReader reads the data and forwards it to the XmlPropertyDeserializer, which deserializes the data into Property. Finally, ObjectFactory converts Property into object.

Please download the source code for more details.

Examples of Advanced Serialization

Following examples are parts of the HelloWorldDemo application which you can download with the source code.

Serialize a Polymorphic Property (where Property Value is Inherited from the Property Type)

There is a property of type IComplexObject. The property value contains a class ComplexObject which is inherited from IComplexObject.

public IComplexObject ComplexObject { get; set; }

There is no need to input the type being serialized. sharpSerializer can serialize the expected type and any inherited type out of the box:

<Complex name="ComplexObject" 
     type="HalloWorldApp.BusinessObjects.ComplexObject, HalloWorldApp">
  <Properties>
    <Simple name="SimpleInt" value="33" />
  </Properties>
</Complex>

Serialize a Generic Dictionary where Values are Inherited from the Interface

There is a generic dictionary where values are of some complex class which is inherited from the interface IComplexObject (polymorphic argument):

public IDictionary<int, IComplexObject> GenericDictionary { get; set; }

It serializes to:

<Dictionary name="GenericDictionaryOfPolymorphicValues" 
          type="System.Collections.Generic.Dictionary`2[[System.Int32, mscorlib],
                   [HalloWorldApp.BusinessObjects.IComplexObject, HalloWorldApp]], 
                   mscorlib" keyType="System.Int32, mscorlib" 
          valueType="HalloWorldApp.BusinessObjects.IComplexObject, HalloWorldApp">
    <Items>
      <Item>
        <Simple value="2012" />
        <Complex type="HalloWorldApp.BusinessObjects.ComplexObject, HalloWorldApp">
          <Properties>
            <Simple name="SimpleInt" value="2012000" />
          </Properties>
        </Complex>
      </Item>
    </Items>
</Dictionary>

As you can see, the type of keys and values does not matter. sharpSerializer can serialize primitive types, complex objects, and even nested listings, e.g., dictionaries.

Serialize a Multidimensional Array

There is a two dimensional array (it could have more dimensions):

public string[,] DoubleArray { get; set; }

It serializes to:

<MultiArray name="DoubleArray" elementType="System.String, mscorlib">
    <Dimensions>
      <Dimension length="3" />
      <Dimension length="2" />
    </Dimensions>
    <Items>
      <Item indexes="0,0">
        <Simple value="k1" />
      </Item>
      <Item indexes="0,1">
        <Simple value="k2" />
      </Item>
      <Item indexes="1,0">
        <Simple value="b1" />
      </Item>
      <Item indexes="1,1">
        <Simple value="b2" />
      </Item>
      <Item indexes="2,0">
        <Simple value="z1" />
      </Item>
      <Item indexes="2,1">
        <Simple value="z2" />
      </Item>
    </Items>
</MultiArray>

It does not matter of what type the array is. sharpSerializer can serialize an array of any object, array of arrays, array of collections, or an array of dictionaries. It can serialize really deep nested arrays.

Serialize an Array of Different Object Types and Array of Arrays (Nested Array)

There is an array of the following objects:

root.SingleArrayOfObjects = new object[] 
{
    42, 
    "nothing to say", 
    false, 
    BusinessObjects.SimpleEnum.Three, 
    null, 
    new object[] 
           {
              42, 
              "nothing to say", 
              false, 
              BusinessObjects.SimpleEnum.Three, 
              null 
           } 
};

It serializes to:

<SingleArray name="SingleArrayOfObjects" elementType="System.Object, mscorlib">
    <Items>
      <Simple type="System.Int32, mscorlib" value="42" />
      <Simple type="System.String, mscorlib" value="nothing to say" />
      <Simple type="System.Boolean, mscorlib" value="False" />
      <Simple type="HalloWorldApp.BusinessObjects.SimpleEnum, 
		HalloWorldApp" value="Three" />
      <Null />
      <SingleArray type="System.Object[], mscorlib" 
		elementType="System.Object, mscorlib">
        <Items>
          <Simple type="System.Int32, mscorlib" value="42" />
          <Simple type="System.String, mscorlib" value="nothing to say" />
          <Simple type="System.Boolean, mscorlib" value="False" />
          <Simple type="HalloWorldApp.BusinessObjects.SimpleEnum, HalloWorldApp" 
        value="Three" />
          <Null />
        </Items>
      </SingleArray>
    </Items>
</SingleArray>

Serialize Other Types

Please download the source code to see the whole example and what else can be serialized. Below are some other properties from the HelloWorldDemo:

public class RootContainer
{
    /// <summary>
    /// Structures are handled as objects during serialization
    /// They are serialized as ComplexProperty
    /// </summary>
    public AdvancedStruct AdvancedStruct { get; set; }

    /// <summary>
    /// Single dimensional array of simple type.
    /// It is serialized as SingleDimensionalArrayProperty
    /// </summary>
    public string[] SingleArray { get; set; }

    /// <summary>
    /// Multidimensional array of simple type.
    /// Is is serialized as MultiDimensionalArrayProperty
    /// </summary>
    public string[,] DoubleArray { get; set; }

    /// <summary>
    /// Single array of derived objects.
    /// This is polymorphic collection - Items derive from the interface
    /// </summary>
    public IComplexObject[] PolymorphicSingleArray { get; set; }

    /// <summary>
    /// Generic list is serialized as a collection.
    /// It is serialized as CollectionProperty
    /// </summary>
    public IList<string> GenericList { get; set; }

    /// <summary>
    /// Polymorphic property. Object instance derives from the property type
    /// Is serialized as ComplexProperty
    /// </summary>
    public IComplexObject ComplexObject { get; set; }

    /// <summary>
    /// Collection where item values are
    /// derived from the collection item type
    /// </summary>
    public ComplexObjectPolymorphicCollection ComplexObjectCollection
                { get; set; }

    /// <summary>
    /// Dictionary where values are derived
    /// from the predefined dictionary value type
    /// </summary>
    public ComplexObjectPolymorphicDictionary ComplexObjectDictionary 
                { get; set; }

    /// <summary>
    /// List items are derived from the generic attribute.
    /// This is polymorphic attribute.
    /// </summary>
    public IList<IComplexObject> GenericListOfComplexObjects { get; set; }

    /// <summary>
    /// Generic object with polymorphic attribute.
    /// It is serialized as ComplexProperty
    /// </summary>
    public GenericObject<IComplexObject> GenericObjectOfComplexObject
                { get; set; }

    /// <summary>
    /// Multidimensional array of generic object with polymorphic attribute
    /// </summary>
    public GenericObject<IComplexObject>[,] 
	MultiArrayOfGenericObjectWithPolymorphicArgument
                { get; set; }
}

public interface IComplexObject { int SimpleInt { get; set; } }

public class ComplexObject : IComplexObject {public int SimpleInt
                { get; set; }}

public class ComplexObjectPolymorphicCollection :
                Collection<IComplexObject>{}

public class ComplexObjectCollection :
                Collection<ComplexObject>{}

public class ComplexObjectPolymorphicDictionary :
                Dictionary<int, IComplexObject>{}

public class ComplexObjectDictionary :
                Dictionary<int, ComplexObject>{}

What do you think? Is XML serialization with sharpSerializer simple enough?

Restrictions of sharpSerializer

In the current version of sharpSerializer, there are some restrictions concerning serialization and deserialization of objects. In the future, these restrictions can be neutralized, but actually they make no such pain. These are:

  • Objects without their public standard constructor cannot be deserialized.
  • Multiple references to the same complex object are not optimized. Such multiple referenced object is serialized as many times as many references to it. (SharpSerializer v.2.9 and above can optimize serializing of multiple references to the same object. Such an object is serialized only once. This optimization results with smaller file size.)

Following limitation concerns serialization in .NET Compact Framework and Silverlight:

  • LowerBound in an array will always be deserialized as 0 regardless of how it was serialized.

LowerBound of an array is not a part of .NET Compact Framework or Silverlight and therefore cannot be handled by the sharpSerializer.

Usage Scenarios

The main reason why I developed sharpSerializer was to save application configuration in an XML file. Few years ago, I was struggling with a polymorphic configuration. I needed a lightweight configuration storage with support for object inheritance. The file should be easily readable and manually editable. The System.Configuration has a big overhead and is too stiff.

The second reason is simple - Silverlight has poor support for the local data repository - it should have a better one :-).
Especially interesting is its possibility to serialize data to the binary format in WP7 (Windows Phone 7).

Download Current Sources

The most recent sources and news are on the project page: www.sharpserializer.com.

Author's Note

If you like sharpSerializer or this article - please rate it. If not, please make a comment below ;-)

History

  • 2011-11-09: Changes according to sharpSerializer v.2.16
  • 2011-10-24: Updated download files
  • 2011-07-31: Updated download files SharpSerializer v.2.12
  • 2011-07-28: Updated download files sharpSerializer v.2.11
  • 2011-05-08: Changes according to sharpSerializer v.2.9, Guid serialization, AttributesToIgnore and optimized serialization of multiple references to the same object
  • 2010-10-07: Updated download files
  • 2010-10-03: Changes according to sharpSerializer v.2.0
  • 2010-05-05: Changes according to sharpSerializer v.1.2
  • 2010-05-04: Added support for the .NET Compact Framework
  • 2010-04-30: Formatting changes (cut off some parts of the big XML example)
  • 2010-04-29: First release

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Pawel idzikowski
Software Developer (Senior) Polenter - Software Solutions
Germany Germany
Member
I'm C# developer from Cologne, Germany. Here I owe a small software company. My hobby is general optimization - natural talent of all lazy guys Wink | ;-)

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralMy vote of 5memberMatthias Muenzner20 Apr '13 - 10:31 
Step in where MS just plain failed... thx alot!
QuestionVote of 5, One Question, ThoughmemberDavid Venegoni2 Jan '13 - 16:39 
Great Article and Awesome Program. Been trying to get some of my complex classes to be saved as user-settings, wondering if I am missing something but is there a way to get my complex classes to persist as user-settings with 'SharpSerializer'?
GeneralInvalidCastException error but really SharpSerializer!!memberDotNetDominator21 Aug '12 - 10:41 
Great work. Really helped me a lot. I had a bunch of existing classes for which I have to add serialization support. I started defining DataContract and Datamember but soon got overwhelmed due to the amount of declarations required. Also, adding attributes to type at run time didn't work for me. Your library solved my problem.
 
I had to disable following lines of code from "createReferenceTargetInstance()" method because I was getting Invalid cast exception in "parseProperties()" method. we have few classes derived from IEnumerable to allow LINQ support for member of the class but class itself is not really a collection class. Following code creates Collection property if type is enumerable which is not always true in our case. It could be bad design on our part which is why I am not making change to actual code. Just posting it here in case someone hit similar issue.
 
            if (typeInfo.IsEnumerable)
            {
                // Actually it would be enough to check if the typeinfo.IsEnumerable is true...
                return new CollectionProperty(name, typeInfo.Type);
            }

GeneralMy vote of 5memberjedijba17 May '12 - 6:35 
Simple and produces a result the XmlSerializer should have been able to in the first place.
QuestionMy vote of 5!memberNiloPaim14 May '12 - 7:38 
Great job. Simple, elegant and functional.
 
Congratulations.
QuestionGreat contribution !!memberboagrius8 Mar '12 - 14:55 
Thank you for posting articles like this, it very helpful.
GeneralGreat Articlememberraananv15 Nov '11 - 10:52 
Great Article!!!
GeneralMy vote of 5memberjim lahey22 Sep '11 - 2:50 
Good work, my 5!
Questionvery nicememberCIDev16 Sep '11 - 3:41 
A well written and useful article.
Just because the code works, it doesn't mean that it is good code.

QuestionGreat work!!!memberDe'lashmate20 Aug '11 - 19:54 
I tried to serialize complex type, with interface propery, generics, and some abstraction,
with xmlSerializer it was hard, ugly, and buggy,
 
Wiht your sharpSerializer it was simple, and elegant! thanks!
AnswerRe: Great work!!!memberPawel idzikowski20 Aug '11 - 22:53 
thanks a lot! If you like, please rate it on [NuGet.org] or Codeplex.com
GeneralMy vote of 5memberFilip D'haene8 Aug '11 - 5:00 
Excellent!
 
Thanks for sharing. Smile | :)
Question=> 5 !memberBillWoodruff2 Aug '11 - 12:38 
Thanks for this ! I've left you some feedback on CodePlex.
 
best, Bill
"In the River of Delights, Panic has not failed me." Jorge Luis Borges

GeneralMy vote of 5memberA.J.Wegierski29 Jul '11 - 19:58 
Special thx for: Multiple references to the same complex object are optimized
GeneralMy vote of 5memberMAD_Den29 Jun '11 - 22:29 
Great job!!!
GeneralMy vote of 5membersam.hill9 May '11 - 8:25 
Impressive work.
Are there comparative benchmarks available (speed of serialization and deserialization)?
GeneralRe: My vote of 5memberPawel idzikowski9 May '11 - 11:29 
thanks! the performance depends on the environment and data being serialized. there is another article comparing SharpSerializer 2.6 with BinaryFormatter: Binary Serialization to Isolated Storage in Silverlight - BinaryFormatter vs. sharpSerializer[^]
GeneralGuid does not serializesmemberCheloXL24 Jan '11 - 11:50 
Hi,
I know why Guid does not serializes, as it does not has public properties. For these use cases, it would be nice to be able to add a resolver in the form of Add(Type type, IResolver resolver) where the resolver could have one method that returns an object with the values I need serialized and another one that takes that object and returns the correct de-serialized type.
GeneralRe: Guid does not serializesmemberPawel idzikowski8 May '11 - 1:43 
hi, SharpSerializer 2.8 and above can serialize Guid. the latest version and sources you find on sharpserializer.codeplex.com
GeneralRequirementsmemberMichal Stehlik4 Oct '10 - 10:02 
Can you please attach some graphs where you compare speed and memory usage of this XML serializer and native one?
GeneralRe: RequirementsmemberPawel idzikowski4 Oct '10 - 16:22 
Like the title says "XML Serialization of a multidimensional Array (...)" I haven't made speed comparison between the built in .NET XmlSerializer and sharpSerializer, because the first one can not serialize such a type at all.
 
There is a speed comparison between BinaryFormatter and sharpSerializer on the project page[^]. Could it be of interest to you? I'll make speed comparisons for simple objects for XmlSerializer and sharpSerializer anyway. Or maybe could you help me, and post your results as an article Wink | ;-)
GeneralMy vote of 4memberHoyaSaxa934 Oct '10 - 9:10 
well done
GeneralRe: My vote of 4memberPawel idzikowski5 Oct '10 - 2:06 
i need 5 Wink | ;-)
QuestionNSerializer comparisonmembercockiest25 Aug '10 - 22:30 
Sound good. How does it compare to nserializer? Does it also support private variables & circular reference serialization?
AnswerRe: NSerializer comparisonmemberPawel idzikowski25 Aug '10 - 23:17 
hi, there is no support for private fields and circular reference is not optimized during xml serialization. when I was writing SharpSerializer i had two main purposes:
 
1) persisting of my configuration classes and sending simple messages, without extended constructors, without private fields etc.
2) making the xml code human readable, thus there is no optimization of circular reference.
 
There is possibility to customize the point 1, like in the FAQ of SharpSerializer:
 
Is it not enough, to filter properties with ExcludeFromSerializationAttribute or PropertiesToIgnore, you can build your CustomPropertyProvider. As a base class there is PropertyProvider, which has two virtual methods GetAllProperties() and IgnoreProperty(...). They can be overwritten to customize the logic.
 
serializer.PropertyProvider = new MyCustomPropertyProvider();
 

There is custom property writer needed to solve the point 2. It can inherit from PropertyWriter which implements the interface IPropertyWriter. Hier you can put the cache-logic. If the same object will be detected, there will be only one instance saved and X references.
 

I think, optimization of circular references in xml code doesn't make sense, as xml self is not optimal way to store data.
 

thanks for your interest on sharpserializer Smile | :)
GeneralRe: NSerializer comparison [modified]membercockiest26 Aug '10 - 1:08 
Thanks for your reply.
I have just tried to serialize a subclass but the property info is missing. For example:
public abstract class A
{
public A(){}
public abstract int Prop1 {get;}
}
 
public class B : A
{
private int prop1 = 1;
public B(){}
public override int Prop1 { get prop1; }
}
 
A obj = new B();
SharpSerializer s = new SharpSerializer();
s.Serialize("C:\abc.xml", obj);
 
It execute without error but I can't find the Prop1 in the xml file's tag.
Is this a limitation of this tool?

modified on Thursday, August 26, 2010 7:16 AM

GeneralRe: NSerializer comparisonmemberPawel idzikowski26 Aug '10 - 1:44 
hi, abstract properties?!. To tell the truth - never heard of them and never missed them yet...Smile | :)
if the code compiles - they must be legal...
it is possible that sharpSerializer does not see them also. My solution would be as follows:
public abstract class A
{
public abstract int Prop1 {get { return getProp1();}
internal abstract int getProp1();
}
 
public class B : A
{
private int prop1 = 1;
 
internal override int getProp1( return 1;);
}
GeneralPolymorphic propertiesmemberscosta_FST11 May '10 - 2:08 
If I understand you say that the standard XML serialization cannot serialize for example a List, with elements Y:X (and/or Z:Y).
I think it is not really correct, I use often the standard XML serialization with this kind of List.
You need to specify the "extra types" involved in the serialization/deserialization:
 
XmlSerializer xmlSerializer = new XmlSerializer(typeof(X), new Type[]{Y,Z});
 

I'm interested in your serializer, but at the moment I cannot try it.
It would be useful to know the performance of your class versus the standard one.
Performance in terms of time to serialize and deserialize big classes.
 
Another question: your class handles only public properties or public fields too?
 
Thank you
GeneralRe: Polymorphic propertiesmemberPawel idzikowski11 May '10 - 2:53 
hi, yes it's true - you can serialize with the XmlSerializer inherited types/polymorphic properties if you overload the constructor and input these types there (as you did it).
 
That's why I say - such a serialization is not possible "out of the box" with the XmlSerializer - you have to feed it with these types every time you serialize them. SharpSerializer doesn't need any additional type information during the serialization.
 
The second thing:
Yes, only public properties can be serialized, not fields. it is not as flexible as one would like to, but as someone other said - a class should be accessible only by its public properties, not its fields (except read only/constant fields). by customizing their get/set methods you have possibility to change their functionality in the future (i.e. convert the string to upper case, validating, raising events...). If you want such a functionality in case of fields, you have to convert them to properties - it brakes the interface. That's why I didn't care about fieldsWink | ;-)
 
Third
That would be nice if sb tests the performance. Actually I have not much time to do this. Thanks in advance!
 
best regards,
Pawel
GeneralRe: Polymorphic propertiesmemberscosta_FST11 May '10 - 20:06 
Thank you Pawel,
I want only point out that sometimes it is necessary to serialize some classes in some assemblies that you have not the possibility to do changes.
And if in this classes are present some public fields?
Moreover using public fileds are not so wrong, I know that this sounds as an heresy to many people.
But I think that if you dont have "code behind" you can use public fields, and you can always convert them to properties without problems.
 
Thank you
GeneralA minor thing (string deserialization)memberPaul898 May '10 - 10:11 
Hi there, already got used to your Serializer and in general it works fine and I really appreciate what you've done Smile | :)
But I've just noticed one thing. I was thinking about sending you a pm, but finally put it here.
Am I right that an object creation method in ObjectFactory class should be more like this? :
 
        private object createObjectFromSimpleProperty(SimpleProperty property)
        {
            // This is the only line I added
            if (property.Type == typeof(string)) return property.Value;
            //
            if (string.IsNullOrEmpty(property.Value)) return null;
 
            return _simpleValueConverter.ConvertFromString(property.Value, property.Type);
        }
 
I mean before adding the check for strings it couldn't deserialize an empty string properly.
(Because string.IsNullOrEmpty(property.Value) == true )
So it was null instead of "".
 
Hope this helps, and you may want to make a patch for your download.
GeneralRe: A minor thing (string deserialization)memberPawel idzikowski8 May '10 - 12:16 
yes, you're right - empty strings were not deserialized. but this source belongs to the very first version of sharpserializer when all simple property values were strings. string as property value was stone in my shoe and very big handycap by developing of binary serializer.
 
Currently (from the version 1.2.0.0) all property values contain any objects, not only strings. The method createObjectFromSimpleProperty looks as below:
 
        private static object createObjectFromSimpleProperty(SimpleProperty property)
        {
            return property.Value;
        }
 
thanks again for your comments
Pawel
GeneralRe: A minor thing (string deserialization)memberPaul899 May '10 - 4:04 
Ok, this solves the issue. I haven't put much attention to the updates, since I wouldn't expect the SharpSerializer is making such a rapid progress.
Thank you for explanation.
GeneralThanksmemberkasiraj7 May '10 - 2:52 
Thanks tis code very usefully in my project
GeneralIncompatibility and other thoughtsmemberstolbovoy4 May '10 - 4:22 
Sorry, for some critic, but I work with serializing ours and other companies data a lot, so just have some comments of what is done. It is a good start, but there is few things that concern me:
 
1) The major task in the complex projects in heterogeneous environment is often [de]serialize into the exact XML format required. This serializer can read what it wrote, but what about that rest of the world?
 
2)What’s wrong with XmlIgnoreAttribute, why new attribute is needed? Most likely people will have models which already decorated with XmlSerializer attributes, to try this one they will need to replace all the attributes which control serialization.
 
3)Another thing it is serializes node names which are useless for data representation purposes and just a waste of space and/or bandwidth (Complex, Properties, Simple). Why serializer can’t distinguish Complex from Simple by the fact of child nodes present?
 
4) “it needs many attributes to define your business objects, i.e.: XmlArrayAttribute, XmlArrayItemAttribute” – XmlSerializer will be perfectly happy without them. These attributes are beneficial to developer who wants to serialize to the exact format he/she needs, but not required.
 
5) “All types are serialized default as "TypeName, AssemblyName" this as a big issue. It is called “tight binding” and it is huge pain in the big projects: different deployment schedules, heterogeneous environment, etc
 
6) “it can not serialize polymorphic properties” – what is this exactly?
Is it something like serializing class D?

public class A{…}
public class B:A {}
public class C:A {}
 
public class D{
public A [] data;
public D ()
{
data = new A[3];
A[0] = new B();
A[1] = new C();
A[2] = new A();
}

GeneralRe: Incompatibility and other thoughtsmemberidzikowski4 May '10 - 5:29 
Ad 1)
Compatibility with the rest of the world is not the primary goal of sharpserializer in its current form. Its strength is in converting objects to propertyCollections. These propertyCollections you can write to any format you need, with your custom IPropertyWriter or IPropertyReader.
 
Ad 2)
Some could associate sharpSerializer only with Xml-Serialization what is not true. Further, there is no use of System.Xml.Serialization in any place. ExcludeFromSerializationAttribute is at the root of the sharpSerializer namespace and is easy to reach. [XmlIgnore] can be handled as well if someone needs it.
 
Ad 3)
Writing Simple, Complex tags is only the matter of the used IPropertyWriter. You can write your own protocol. As default there is XmlPropertyWrite in use which has such a syntax.
 
Ad 4)
What about array X[] where array elements are of type Y where Y:X – similar to polymorphic properties? See my answer 6
 
Ad 5)
I haven’t thought about big companies during the work on sharpserializer. All I needed was simple serializer, which serializes data from my PC and deserializes it on my Pocket PC, disregarding different assembly versions, target platforms, schemas, namespaces and security issues.
 
Ad 6)
It is exactly what you mean. The declared property is of the type X, but it contains value of the type Y, where Y:X. I’ve seen once this term in the enterprise library, there was PolymorphicConfigurationItem or sth like that.
 
Thanks for your critic, I didn’t expected, someone studies my work as extensive as you have done it. I didn’t even expected someone reads this article Wink | ;-)
GeneralRe: Incompatibility and other thoughtsmemberstolbovoy4 May '10 - 6:45 
So 4) and 6) are really about using XmlIncludeAttribute and XmlArrayItemIttributes
Thanks you for the reply and for the article. I understand it now. It is really useful for me to see the world outside of my box Smile | :)
GeneralRe: Incompatibility and other thoughtsmemberMoim Hossain5 May '10 - 9:59 
Considering the goals that the author has mentioned here, I believe this is a very nice API to do simple serialization tasks. I will definitely use this next time I do some serialization. You got my five.
 
Regarding the type name that you preserve into the xml:
 
Usually the serialized xml will have a same type name string (i.e. TypeName, AssemblyName, Culture...) several times (especially for the collections). This is really increase the size of the xml text. Would it be wise to use a catalog of used type names and a "generated unique token" at the beginning section of the xml and then use that token into the actual data nodes instead of the type name? This can significantly reduce the size of the serialized data. Just a thought Smile | :)
 
I liked your idea and implementation. All the best !
Moim Hossain
R&D Project Manager
BlueCielo ECM Solutions BV

GeneralRe: Incompatibility and other thoughts [modified]memberidzikowski5 May '10 - 12:31 
hi Moim, there is plenty of place for improvements. i think actually to use such a dictionary where key is the token, and the value is the type name in the new binary serializer. you're right, type names take much place. they should be only once defined and then referenced. though xml without the dictionary looks clearer, but in a binary file, it should be implemented.
 
New content:
hi again Moim, the binary serialization is already implemented. Just as you wish. Types and property names are grouped in a dictionary at the beginning of the serialized file. Objects reference this dictionary. More details - Search for "BinarySerializationMode.SizeOptimized" on the project page.
 
cheers
Pawel

modified on Tuesday, October 5, 2010 9:05 AM

GeneralThanks!memberPaul8930 Apr '10 - 8:49 
The tool you provided is really, really good. Exceptionally useful. Additionally it's right on time - added one day before I found I'll need something like that Big Grin | :-D
 
One thing, though, is a slight imperfection for me. After serialization all objects are marked with an identifier like "Complex" or "Simple". I guess this may be less readable, especially for an 'external' user. He has right to have no clue about what 'Simple' is, when he opens a settings file. On the other hand, I like this technique, because it's very coherent. You know that the syntax of an xml file will always be the same. I was just wondering if one can avoid the 'Simple'/'Complex' (etc.) tokens without a performance hit and hours of coding.
 
However, what I'm saying is probably a babble. Good job, got my 5!
GeneralRe: Thanks!memberidzikowski30 Apr '10 - 9:24 
hi Paul, thank you! Bad luck - there are more different tags as only Simple and Complex. All mentioned in the Kapitel "How does the sharpSerializer work" properties have their own Tags. Additionally there are some common Tags as "Items, Item, Properties...".
 
If I use the same name for all the Tags, it would be necessary to use an additional attribute to indentify the property type. I'm not sure, if it would be better...
 
For an "external" user you should simply write a comment: "manual editing of this xml file is extremely hazardous!" Wink | ;-)
GeneralJSON comparisonmemberBrad Bruce28 Apr '10 - 15:41 
How does this compare to using JSON? Did you run into a situation where you had to use XML and couldn't use something like JSON?
 
Nice article. I'll keep it in mind for the XML only situations I run into sometimes.
GeneralRe: JSON comparisonmemberidzikowski28 Apr '10 - 20:00 
thank you!I have not used JSON yet, but that what I found - JSON does not support:
1)Arrays of arrays,
2)Arrays that contain elements of different types. Example: [ 100, { "foo": "bar" }, true, null ]
 
sharpSerializer does it.
GeneralI approved this, but...memberJohn Simmons / outlaw programmer28 Apr '10 - 3:07 
...you have to format your code snippets so that they don't require us to have to horizontally scroll our browser to see it all.
.45 ACP - because shooting twice is just silly
-----
"Why don't you tie a kerosene-soaked rag around your ankles so the ants won't climb up and eat your candy ass..." - Dale Earnhardt, 1997
-----
"The staggering layers of obscenity in your statement make it a work of art on so many levels." - J. Jystad, 2001

GeneralRe: I approved this, but...memberidzikowski28 Apr '10 - 8:01 
Thank you! It's my first time. I'm a little bit nervous Wink | ;-)

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web02 | 2.6.130523.1 | Last Updated 9 Nov 2011
Article Copyright 2010 by Pawel idzikowski
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid