2

I an using DataContractSerializer and i want to separate data of same object into multiple files.

[DataContract]
public class TestObj
{
    [DataMember]
    protected double field1 = 0.0;

    [DataMember]
    protected double field2 = 0.0;
}

Specifically I want to save field1 in one XML file and field2 in a different XML file. Is there any way to do that using data contract serialization?

This is how I am serializing currently:

DataContractSerializer serializaer = new DataContractSerializer(GetType(), null,
              0x7FFFFFFF /*maxItemsInObjectGraph*/,
              false /*ignoreExtensionDataObject*/,
              true /*preserveObjectReferences : this is most important to me */,
              null /*dataContractSurrogate*/);
var fs = File.Open(fName, FileMode.Create);
serializaer.WriteObject(fs, this);

fs.Dispose();
return true;
dbc
  • 104,963
  • 20
  • 228
  • 340
  • Possible duplicate of [How to Split an XML file into multiple XML Files](https://stackoverflow.com/questions/12016946/how-to-split-an-xml-file-into-multiple-xml-files) – tymtam Oct 13 '19 at 12:36
  • no, that means i will serliaze whole object into xml file then split it to two xml files and that will consume alot ! – Ameer Mansour Oct 13 '19 at 12:44
  • Consume a lot of what? – tymtam Oct 13 '19 at 12:46
  • lot of time to serlaize and then split , i have an object contains lot of fields and some of these fields are classes which consists of lot of fields as well. – Ameer Mansour Oct 13 '19 at 12:49
  • i edited the question please check it . – Ameer Mansour Oct 13 '19 at 12:50
  • And how are you going to deserialize this splitted data? – Alexander Petrov Oct 13 '19 at 18:05
  • 1
    You could use the [`IDataContractSurrogate`](https://learn.microsoft.com/en-us/dotnet/framework/wcf/extending/data-contract-surrogates) mechanism for this. See e.g. [How to serialize / deserialize immutable list type in c#](https://stackoverflow.com/a/18957739/3744182), [partial or full object serialization](https://stackoverflow.com/a/25456638/3744182), [WCF Extensibility – Serialization Surrogates](https://blogs.msdn.microsoft.com/carlosfigueira/2011/09/13/wcf-extensibility-serialization-surrogates/). – dbc Oct 14 '19 at 18:12

2 Answers2

1

I can suggest using Custom Xml Writer paired with serializer.

public class CustomWriter : XmlTextWriter
{
    public CustomWriter(TextWriter writer) : base(writer) { }
    public CustomWriter(Stream stream, Encoding encoding) : base(stream, encoding) { }
    public CustomWriter(string filename, Encoding encoding) : base(filename, encoding) { }

    public List<string> FieldList { get; set; }

    private string _localName;

    public override void WriteStartElement(string prefix, string localName, string ns)
    {
        if (!FieldList.Contains(localName))
            base.WriteStartElement(prefix, localName, ns);
        else
            _localName = localName;
    }

    public override void WriteString(string text)
    {
        if (!FieldList.Contains(_localName))
            base.WriteString(text);
    }

    public override void WriteEndElement()
    {
        if (!FieldList.Contains(_localName))
            base.WriteEndElement();
        else
            _localName = null;
    }
}

Use it as follows:

var data = new TestObj();

var serializer = new DataContractSerializer(
    typeof(TestObj), null, 0x7FFFFFFF, false, true, null);

using (var writer = new CustomWriter(Console.Out)) // Specify filename or stream instead
{
    writer.Formatting = Formatting.Indented;
    writer.FieldList = new List<string> { "field1", "field3" }; // Specify fields to ignore
    serializer.WriteObject(writer, data);
}

Just specify a list of fields that should be ignored in the FieldList property.

Of course, with this way, the DataContractSerializer will intermediate create xml with all the elements contained in the class. And only after that our custom writer will filter them. But it will happen on the fly, very quickly and effectively.

Alexander Petrov
  • 13,457
  • 2
  • 20
  • 49
  • that's sounds perfect to me ! i will try it but will it work when i deseliaze it ? `DataContractSerializer serializaer = new DataContractSerializer(typeof(TestObj)); var fs = File.Open(fName, FileMode.Open); var myserializaedObject= serializaer.ReadObject(fs) as TestObj; fs.Dispose();` where fName is file path of file1 and then i call it again with file 2 ? – Ameer Mansour Oct 14 '19 at 10:51
  • 1
    @AmeerMansour - *will it work when i deseliaze it ?* - your question only mentions serialization not **de**serialization. You might want to clarify your question, or ask another question. – dbc Oct 14 '19 at 18:13
  • @AmeerMansour - To deserialize data into a single whole from several files, we can try to write a custom xml reader in the same way. If necessary, ask a new question. – Alexander Petrov Oct 16 '19 at 23:06
0

Once you serialise the whole object you can then split it using Linq to XML.

Oh, I even found an example how to do it at How to Split an XML file into multiple XML Files.

tymtam
  • 31,798
  • 8
  • 86
  • 126
  • it will consume lot of time to serlaize and then split , i have an object contains lot of fields and some of these fields are classes which consists of lot of fields as well. – Ameer Mansour Oct 13 '19 at 12:54