Logging Experiences

How to serialize DataTable and DataSet objects with YAXLib

Posted in C#, Programming, YAXLib by Sina Iravanian on October 24, 2012

YAXLib 2.x does not support serializing DataSet and DataTable objects by default. Since they have public properties of their own type, one will receive a YAXCannotSerializeSelfReferentialTypes exception. But it is quite possible to serialize them with custom serializers. Below is defined a custom serializer for DataSet:

public class DataSetCustomSerializer : ICustomSerializer<DataSet>
{
    public DataSet DeserializeFromElement(System.Xml.Linq.XElement element)
    {
        var child = element.Elements().FirstOrDefault();
        if(child == null)
            return null;
        using (var xr = child.CreateReader())
        {
            DataSet ds = new DataSet();
            var readMode = ds.ReadXml(xr);
            return ds;
        }
    }

    public void SerializeToElement(DataSet objectToSerialize, System.Xml.Linq.XElement elemToFill)
    {
        using (var xw = elemToFill.CreateWriter())
        {
            objectToSerialize.WriteXml(xw);
        }
    }

    public DataSet DeserializeFromAttribute(System.Xml.Linq.XAttribute attrib)
    {
        throw new NotImplementedException();
    }

    public DataSet DeserializeFromValue(string value)
    {
        throw new NotImplementedException();
    }

    public void SerializeToAttribute(DataSet objectToSerialize, System.Xml.Linq.XAttribute attrToFill)
    {
        throw new NotImplementedException();
    }

    public string SerializeToValue(DataSet objectToSerialize)
    {
        throw new NotImplementedException();
    }
}

And this is a custom serializer for DataTable:

public class DataTableCustomSerializer : ICustomSerializer<DataTable>
{
    public DataTable DeserializeFromElement(System.Xml.Linq.XElement element)
    {
        var dsElem = element.Elements().Where(x => x.Name.LocalName == "NewDataSet").FirstOrDefault();
        if (dsElem == null)
            return null;

        using (var xr = dsElem.CreateReader())
        {
            DataSet ds = new DataSet();
            var readMode = ds.ReadXml(xr);
            if(ds.Tables.Count > 0)
                return ds.Tables[0].Copy();
            return null;
        }
    }

    public void SerializeToElement(DataTable objectToSerialize, System.Xml.Linq.XElement elemToFill)
    {
        using (var xw = elemToFill.CreateWriter())
        {
            DataSet ds = new DataSet();
            ds.Tables.Add(objectToSerialize.Copy());
            ds.WriteXml(xw);
        }
    }

    public DataTable DeserializeFromAttribute(System.Xml.Linq.XAttribute attrib)
    {
        throw new NotImplementedException();
    }

    public DataTable DeserializeFromValue(string value)
    {
        throw new NotImplementedException();
    }

    public void SerializeToAttribute(DataTable objectToSerialize, System.Xml.Linq.XAttribute attrToFill)
    {
        throw new NotImplementedException();
    }

    public string SerializeToValue(DataTable objectToSerialize)
    {
        throw new NotImplementedException();
    }
}

Having the above custom serializers at hand, one can decorate the DataSet and DataTable properties (or fields) with the YAXCustomSerializer attribute fed with the appropriate custom serializer type, as demonstrated below:

public class DataSerializationDemo
{
    [YAXCustomSerializer(typeof(DataTableCustomSerializer))]
    public DataTable TheDataTable { get; set; }

    [YAXCustomSerializer(typeof(DataSetCustomSerializer))]
    public DataSet TheDataSet { get; set; }
}

The following provides a sample instantiation for the above class:

public static DataSerializationDemo GetSampleInstance()
{
    var dataTable = new DataTable("TableName", "http://tableNs/");
    dataTable.Columns.Add(new DataColumn("Col1", typeof(string)));
    dataTable.Columns.Add(new DataColumn("Col2", typeof(int)));
    dataTable.Columns.Add(new DataColumn("Col3", typeof(string)));

    dataTable.Rows.Add("1", 2, "3");
    dataTable.Rows.Add("y", 4, "n");

    var dataTable1 = new DataTable("Table1");
    dataTable1.Columns.Add(new DataColumn("Cl1", typeof(string)));
    dataTable1.Columns.Add(new DataColumn("Cl2", typeof(int)));

    dataTable1.Rows.Add("num1", 34);
    dataTable1.Rows.Add("num2", 54);

    var dataTable2 = new DataTable("Table2");
    dataTable2.Columns.Add(new DataColumn("C1", typeof(string)));
    dataTable2.Columns.Add(new DataColumn("C2", typeof(int)));
    dataTable2.Columns.Add(new DataColumn("C3", typeof(double)));

    dataTable2.Rows.Add("one", 1, 1.5);
    dataTable2.Rows.Add("two", 2, 2.5);

    var dataSet = new DataSet("MyDataSet");
    dataSet.Tables.AddRange(new[] { dataTable1, dataTable2 });

    return new DataSerializationDemo
    {
        TheDataTable = dataTable,
        TheDataSet = dataSet
    };
}

And the following is the XML result for serializing the above object:

<DataSerializationDemo>
  <TheDataTable>
    <NewDataSet>
      <TableName xmlns="http://tableNs/">
        <Col1>1</Col1>
        <Col2>2</Col2>
        <Col3>3</Col3>
      </TableName>
      <TableName xmlns="http://tableNs/">
        <Col1>y</Col1>
        <Col2>4</Col2>
        <Col3>n</Col3>
      </TableName>
    </NewDataSet>
  </TheDataTable>
  <TheDataSet>
    <MyDataSet>
      <Table1>
        <Cl1>num1</Cl1>
        <Cl2>34</Cl2>
      </Table1>
      <Table1>
        <Cl1>num2</Cl1>
        <Cl2>54</Cl2>
      </Table1>
      <Table2>
        <C1>one</C1>
        <C2>1</C2>
        <C3>1.5</C3>
      </Table2>
      <Table2>
        <C1>two</C1>
        <C2>2</C2>
        <C3>2.5</C3>
      </Table2>
    </MyDataSet>
  </TheDataSet>
</DataSerializationDemo>

Please note that all the above steps are provided for YAXLib 2.x, which may require slight modifications in future versions of the library.

Advertisements

YAXLib is Now Hosted on GitHub Too

Posted in Programming by Sina Iravanian on May 14, 2012

YAXLib is an XML serialization library which focuses on XML formatting, and creating human-editable results. To know more about YAXLib read this CodeProject article. It was originally hosted on CodePlex, under the SVN source-control. Now, hoping more contribution from the community, the source-control of YAXLib on CodePlex is changed to Git. Besides, YAXLib is hosted on GitHub too. So, feel free to fork YAXLib on either CodePlex or GitHub.

Tagged with:

YAXLib is now hosted on CodePlex

Posted in Programming by Sina Iravanian on May 16, 2010

I decided to create a project on CodePlex and host YAXLib there. Previously YAXLib was hosted on SourceForge as a part of the Code4Public project. I’m going to move Code4Public to CodePlex very soon.

This is the link to YAXLib on CodePlex:
http://yaxlib.codeplex.com

Tagged with:

YAXLib 2.0 is Released

Posted in C#, Programming by Sina Iravanian on April 17, 2010

I am finally finished with YAXLib 2.0. The CodeProject article is available here [+], and the source code is available from here [+].

See the ChangeLog file to see what is new, and read the CodeProject article and run the demo application to see what are the capabilities of the library. In short I can name these:

  • Structure freely the XML Result.
  • Serialize all known generic and non-generic collection classes in System.Collections, and System.Collections.Generic
  • Serialize single-dimensional, multi-dimensional, and jagged arrays.
  • Support for specifying path-like serialization addresses, e.g., "elem1/elem2/elem3", and "../elem1", and "./elem1".
  • Specify aliases for enums.
  • Choose the fields to serialize (public, or non-public properties, or member variables).
  • Serialize and deserialize objects through a reference to their base-class or interface.
  • Support for multi-stage deserialization,
  • and more …

The most joyful implementation parts of this library was adding the support for serialization and deserialization of multi-dimensional, and jagged arrays, and also the support for serialization and deserialization of objects through a reference to their base-class or interface.

Please let me know your bug reports and feature requests.

Tagged with: , ,