I have an Album class which contains title, description and an integer value of the index of a cover image. It also contains an imageList.
I need to serialize this obj and while the imageList is not serializeable but the imageListStream is...
I'm a complete c# noob so would appreciate what ever guidance available.
The desired result would be somethings like:
<Album>
<Title>Album Title</Title>
<Description>Some explanation.</Description>
<CoverImgIndx>2</CoverImgIdx>
<Images>
<Image>
<indx>0</indx>
<filepath>"C:\Images\file1.jpg"</filepath>
</Image>
<Image>
<indx>1</indx>
<filepath>"C:\Images\file2.png"</filepath>
</Image>
<Image>
<indx>2</indx>
<filepath>"C:\Images\file3.jpg"</filepath>
</Image>
<Image>
<indx>3</indx>
<filepath>"C:\Images\file4.bmp"</filepath>
</Image>
</Images>
</Album>
obviously I need to reconstitute the imageList when deserializing...
Sounds like you simply need to use the XmlSerializer class to serialize your Album class into XML.
Something like this should work: https://dotnetfiddle.net/yE8RAl
Generally speaking you can define your Album / Image like this:
[XmlType(TypeName = "Image")]
public class ImageSerializationContainer
{
[XmlElement(ElementName = "indx")]
public int Index { get; set; }
[XmlElement(ElementName = "filepath")]
public string FilePath { get; set; }
}
[XmlType(TypeName = "Album")]
public class AlbumSerializationContainer
{
public string Title { get; set; }
public string Description { get; set; }
public int CoverImgIndx { get; set; }
public List<ImageSerializationContainer> Images { get; set; }
}
And then use XmlSerializer like this:
XmlSerializer ser = new XmlSerializer(typeof(AlbumSerializationContainer));
StringWriter sw = new StringWriter();
ser.Serialize(sw, yourObjectToSerialize);
return sw.ToString();
However I'm guessing that what you really want is to somehow convert your existing class in a form that you can serialize.
Unfortunately you don't give a lot to go on in your question, so I have to make some assumptions. Now, some of this assumptions are bound to be wrong, but that's to be expected with the level of information you have provided.
I'm going to assume that you are using the ImageList class and that the filenames that you have in your example are stored in a string array that is attached to the ImageList Tag property. Feel free to modify the code to take this value from elsewhere. You did not give information about how you structure your index values. I'm assuming these are indexes in the ImageList.Images collection.
There are several ways to approach your problem. I'm going to show you how to use AutoMapper to convert what could be your class to a class that you can serialize and then serialize it.
Below you can find a complete example. Please note that you might need to update the AutoMapper configuration if your classes are different from presented below.
I'm demonstrating both: serializing an class to XML (example 1) and converting another class to serializable class (example 2).
using System;
using System.IO;
using System.Drawing;
using System.Windows.Forms;
using System.Xml.Serialization;
using System.Collections.Generic;
using AutoMapper;
namespace SO24174411
{
class Program
{
static void Main()
{
AlbumSerializationContainer example1 = new AlbumSerializationContainer
{
CoverImgIndx = 2,
Description = "Some explanation.",
Images = new List<ImageSerializationContainer>
{
new ImageSerializationContainer {FilePath = #"C:\Images\file1.jpg", Index = 0},
new ImageSerializationContainer {FilePath = #"C:\Images\file2.png", Index = 1},
new ImageSerializationContainer {FilePath = #"C:\Images\file3.jpg", Index = 2},
new ImageSerializationContainer {FilePath = #"C:\Images\file4.bmp", Index = 3}
},
Title = "Album Title"
};
Console.WriteLine("Example 1");
Console.WriteLine(Serialize(example1));
Album album = new Album
{
CoverImgIndx = 2,
Description = "Some explanation.",
Images = new ImageList(),
Title = "Album Title"
};
SetImages(album.Images, new[]
{
#"C:\Images\file1.jpg",
#"C:\Images\file1.jpg",
#"C:\Images\file2.png",
#"C:\Images\file4.bmp"
});
var example2 = PerformMapping(album);
Console.WriteLine("Example 2");
Console.WriteLine(Serialize(example2));
}
private static AlbumSerializationContainer PerformMapping(Album album)
{
Mapper.CreateMap<Album, AlbumSerializationContainer>();
Mapper.CreateMap<ImageList, List<ImageSerializationContainer>>().ConvertUsing<ImageListconverter>();
AlbumSerializationContainer example2 = Mapper.Map<AlbumSerializationContainer>(album);
return example2;
}
public class ImageListconverter : TypeConverter<ImageList, List<ImageSerializationContainer>>
{
protected override List<ImageSerializationContainer> ConvertCore(ImageList source)
{
if (source == null)
{
return null;
}
List<ImageSerializationContainer> result = new List<ImageSerializationContainer>();
for (int i = 0; i < source.Images.Count; i++)
{
result.Add(new ImageSerializationContainer { FilePath = ((string[])source.Tag)[i], Index = i });
}
return result;
}
}
public static string Serialize(AlbumSerializationContainer a)
{
XmlSerializer ser = new XmlSerializer(typeof(AlbumSerializationContainer));
StringWriter sw = new StringWriter();
ser.Serialize(sw, a);
return sw.ToString();
}
public static void SetImages(ImageList l, string[] names)
{
l.Tag = names;
for(int i=0;i<names.Length;i++)
{
// Aparently you can read names[i] file here if you want
l.Images.Add(new Bitmap(1, 1));
}
}
}
public class Album
{
public string Title { get; set; }
public string Description { get; set; }
public int CoverImgIndx { get; set; }
public ImageList Images { get; set; }
}
[XmlType(TypeName = "Image")]
public class ImageSerializationContainer
{
[XmlElement(ElementName = "indx")]
public int Index { get; set; }
[XmlElement(ElementName = "filepath")]
public string FilePath { get; set; }
}
[XmlType(TypeName = "Album")]
public class AlbumSerializationContainer
{
public string Title { get; set; }
public string Description { get; set; }
public int CoverImgIndx { get; set; }
public List<ImageSerializationContainer> Images { get; set; }
}
}
You will be able to easily de-serialize your xml back to the serialization container class with XmlSerializer.Deserialize. Some more work will be required to map these back to your required class. Since this part depends more than any other on the information you have not provided I leave it as an exercise for the reader.
Related
i have an application that has to deserialize an array of data wrapped in a "results" Root Object, using Netwonsoft.Json package from NuGet
The Json string is exactly this:
{"results":[{"Coin":"SBD","LP":0.000269,"PBV":-54.36,"MACD1M":true,"MACD30M":true,"MACD1H":true,"MACD1D":true},{"Coin":"XMR","LP":0.027135,"PBV":11.44,"MACD1M":true,"MACD30M":true,"MACD1H":true,"MACD1D":true}]}
This Json string is created from a Console App i made, i wanted it to look like this https://bittrex.com/Api/v2.0/pub/market/GetTicks?marketName=BTC-NEO&tickInterval=hour
My class looks like this
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WindowsFormsApp2
{
public class Result
{
public string Coins { get; set; }
public decimal LastPrice { get; set; }
public decimal PercentBuyVolume { get; set; }
}
public class RootObject
{
public List<Result> results { get; set; }
}
}
In the Main form i have a function to download from a URL that Json (i have XAMPP running Apache) and deserialize it in an array. And it looks like this:
private void DownloadBittrexData()
{
int PanelID = 0;
var Coin = new List<string>();
var LastPrice = new List<decimal>();
var PercentBuyVolume = new List<decimal>();
var MACD1M = new List<bool>();
var MACD30M = new List<bool>();
var MACD1H = new List<bool>();
var MACD1D = new List<bool>();
var client = new WebClient();
var URL = client.DownloadString("http://localhost/test.json");
Console.WriteLine("Json String from URL: " + URL);
var dataDeserialized = JsonConvert.DeserializeObject<RootObject>(URL);
foreach (var data in dataDeserialized.results)
{
Coin.Add(data.Coins);
LastPrice.Add(data.LastPrice);
PercentBuyVolume.Add(data.PercentBuyVolume);
}
int sizeOfArrayClose = Coin.Count - 1;
for (int i = 0; i <= sizeOfArrayClose; i++)
{
Console.WriteLine("Coin: " + Coin[i]);
Console.WriteLine("Lastprice: " + LastPrice[i]);
Console.WriteLine("PBV: " + PercentBuyVolume[i]);
}
}
Newtonsoft.Json is of course declared at the beginning of the form together with System.Net
using System.Net;
using Newtonsoft.Json;
The output looks like this:
Json String from URL: {"results":[{"Coin":"SBD","LP":0.000269,"PBV":-54.36,"MACD1M":true,"MACD30M":true,"MACD1H":true,"MACD1D":true},{"Coin":"XMR","LP":0.027135,"PBV":11.44,"MACD1M":true,"MACD30M":true,"MACD1H":true,"MACD1D":true}]}
Coin:
Lastprice: 0
PBV: 0
Coin:
Lastprice: 0
PBV: 0
It's like it fails to deserialize it after downloading it.
What should i do? Thank you very much.
Your property names don't map to the field names in the JSON. You could rename your C# properties to match the JSON, but it would make for unreadable downstream code.
Instead, you should map your properties (with nice, readable names) to the names that appear in the JSON, using JsonPropertyAttribute:
public class Result
{
public string Coin { get; set; } //didn't bother here: changed property name to Coin
[JsonProperty("LP")]
public decimal LastPrice { get; set; }
[JsonProperty("PBV")]
public decimal PercentBuyVolume { get; set; }
}
your model should be like this for deserialize json
public class Result
{
public string Coin { get; set; }
public double LP { get; set; }
public double PBV { get; set; }
public bool MACD1M { get; set; }
public bool MACD30M { get; set; }
public bool MACD1H { get; set; }
public bool MACD1D { get; set; }
}
public class RootObject
{
public List<Result> results { get; set; }
}
LastPrice and PercentBuyVolume are not available in your model that's the reason it's getting an error.
I tried your exact code on my system and I was able to retrieve the result as expected. Hope this helps, It's easy to understand.
Here is the main class
static void Main(string[] args)
{
RootObject configfile = LoadJson();
foreach (var tResult in configfile.results)
{
Console.WriteLine("Coin: " + tResult.Coin);
Console.WriteLine("Lastprice: " + tResult.LP);
Console.WriteLine("PBV: " + tResult.PBV);
}
Console.ReadLine();
}
LoadJson Function would be
private static RootObject LoadJson()
{
string json = "{\"results\":[{\"Coin\":\"SBD\",\"LP\":0.000269,\"PBV\":-54.36,\"MACD1M\":true,\"MACD30M\":true,\"MACD1H\":true,\"MACD1D\":true},{\"Coin\":\"XMR\",\"LP\":0.027135,\"PBV\":11.44,\"MACD1M\":true,\"MACD30M\":true,\"MACD1H\":true,\"MACD1D\":true}]}";
RootObject configs = Deserialize<RootObject>(json);
return configs;
}
and Deserialize function would be
private static T Deserialize<T>(string json)
{
T unsecureResult;
string _DateTypeFormat = "yyyy-MM-dd HH:mm:ss";
DataContractJsonSerializerSettings serializerSettings = new DataContractJsonSerializerSettings();
DataContractJsonSerializer serializer;
MemoryStream ms;
unsecureResult = default(T);
serializerSettings.DateTimeFormat = new System.Runtime.Serialization.DateTimeFormat(_DateTypeFormat);
serializer = new DataContractJsonSerializer(typeof(T));
ms = new MemoryStream(Encoding.Unicode.GetBytes(json));
unsecureResult = (T)serializer.ReadObject(ms);
return unsecureResult;
}
and Now your Datamodel would be
public class Result
{
public string Coin { get; set; }
public double LP { get; set; }
public double PBV { get; set; }
public bool MACD1M { get; set; }
public bool MACD30M { get; set; }
public bool MACD1H { get; set; }
public bool MACD1D { get; set; }
}
public class RootObject
{
public List<Result> results { get; set; }
}
So, I have XML like this:
<tileset firstgid="1" name="simple_tiles" tilewidth="32" tileheight="32" tilecount="16" columns="8">
<image source="../Users/mkkek/Pictures/rpg/default_tiles_x.png" width="256" height="64"/>
</tileset>
When I'm at the tileset node, how can I access the image node and its source attribute? My code is as follows:
public void LoadMaps(ContentManager content)
{
Dictionary<string, string> mapsToLoad = InitMapsToLoad();
foreach (KeyValuePair<string, string> mapToLoad in mapsToLoad)
{
Map map = new Map();
map.Name = Path.GetFileNameWithoutExtension(mapToLoad.Value);
reader = XmlReader.Create("Content/" + mapToLoad.Value);
while(reader.Read())
{
if(reader.NodeType == XmlNodeType.Element)
{
switch(reader.Name)
{
case "tileset":
if(!Tilesets.Any(ts => ts.Name == reader.GetAttribute("name")))
{
// handling the image node here
}
break;
}
}
}
}
}
I usually prefer to use LINQ to XML because I find it's API to be much easier to use than XmlReader, a comparison between the technologies here.
If all you need is getting source attribute value from image element this can be achieved easily:
var doc = XDocument.Load("something.xml");
var root = doc.DocumentElement;
var imageElements = root.Elements("image").ToList();
foreach (var imageElement in imageElements)
{
var sourceAttribute = imageElement.Attribute("source");
var sourceValue = sourceAttribute.Value;
//do something with the source value...
}
More about basic queries in LINQ to XML here.
I will suggest to create some classes that represents the Xml structure, something like this :
[XmlRoot(ElementName = "image")]
public class Image
{
[XmlAttribute(AttributeName = "source")]
public string Source { get; set; }
[XmlAttribute(AttributeName = "width")]
public string Width { get; set; }
[XmlAttribute(AttributeName = "height")]
public string Height { get; set; }
}
[XmlRoot(ElementName = "tileset")]
public class Tileset
{
[XmlElement(ElementName = "image")]
public Image Image { get; set; }
[XmlAttribute(AttributeName = "firstgid")]
public string Firstgid { get; set; }
[XmlAttribute(AttributeName = "name")]
public string Name { get; set; }
[XmlAttribute(AttributeName = "tilewidth")]
public string Tilewidth { get; set; }
[XmlAttribute(AttributeName = "tileheight")]
public string Tileheight { get; set; }
[XmlAttribute(AttributeName = "tilecount")]
public string Tilecount { get; set; }
[XmlAttribute(AttributeName = "columns")]
public string Columns { get; set; }
}
Then In some Utility class add the following method:
public static T DeserializeFromXml<T>(string xml)
{
if (string.IsNullOrEmpty(xml))
{
return default(T);
}
var serializer = new XmlSerializer(typeof(T));
T entity;
using (XmlReader reader = XmlReader.Create(new StringReader(xml)))
{
entity = (T)serializer.Deserialize(reader);
}
return entity;
}
Now you will be able to access to the Image object using the following code:
Tileset tileset=DeserializeFromXml<Tileset>(yourXmlContent);
// now you can access the image from the tileset instance 'tileset.Image.Source'
You are almost done. Add this to your code.
// handling the image node here
if (reader.ReadToDescendant("image"))
{
string source = reader.GetAttribute("source");
}
I have the follow XML structure:
<Document>
<Sectors>
<Sector>
SectorName1
<Subsectors>
<Subsector>Subsector1</Subsector>
<Subsector>Subsector2</Subsector>
</Subsectors>
</Sector>
<Sector>
SectorName2
<Subsectors>
<Subsector>Subsector1</Subsector>
<Subsector>Subsector2</Subsector>
</Subsectors>
</Sector>
</Sectors>
</Document>
Also I have classes for deserialize:
public class MetaDataXML
{
public class SectorXML
{
[XmlArrayItem(ElementName = "Sector")]
string SectorName { get; set; }
[XmlArray]
[XmlArrayItem(ElementName = "Subsector")]
public List<string> Subsectors { get; set; }
}
public List<SectorXML> Sectors { get; set; }
}
And part of code which do deserialize:
var xRoot = new XmlRootAttribute { ElementName = "Document", IsNullable = true };
var reader = new XmlSerializer(typeof(MetaDataXML), xRoot);
var data = (MetaDataXML)reader.Deserialize(streamXML);
After deserialization I successfully get subsectors velues, but I didn't get values for SectorName. How I need to organize my structure of class that I'll get values "SectorName1" and "SectorName2" for my string SectorName property?
I found that that this case it's a "Mixed Content". How we can parse this text values?
Whilst I am not entirely sure what it is you're trying to achieve here, I've made a few modifications to your XML class and provided some sample code below that is able to retrieve all of the information about a sector, including its name and the name of all the subsectors inside it.
XML Class:
namespace DocumentXml
{
[XmlRoot("Document")]
public class Document
{
[XmlArray("Sectors")]
[XmlArrayItem("Sector")]
public Sector[] Sectors { get; set; }
}
[XmlRoot("Sector")]
public class Sector
{
[XmlAttribute("SectorName")]
public string SectorName { get; set; }
[XmlArray("Subsectors")]
[XmlArrayItem("Subsector")]
public string[] Subsectors { get; set; }
}
}
Main Program Class:
namespace DocumentXml
{
class Program
{
static void Main(string[] args)
{
var path = #"D:\sandbox\DocumentXml\DocumentXml\Sample.xml";
var serializer = new XmlSerializer(typeof(Document));
var document = serializer.Deserialize(File.OpenRead(path)) as Document;
var sectors = document.Sectors;
foreach (var s in sectors)
{
Console.WriteLine($"Sector Name: {s.SectorName}");
foreach (var ss in s.Subsectors)
{
Console.WriteLine($"Subsector Name: {ss}");
}
Console.WriteLine();
}
Console.ReadKey();
}
}
}
Sample XML:
<Document>
<Sectors>
<Sector SectorName="SectorName1">
<Subsectors>
<Subsector>Subsector1</Subsector>
<Subsector>Subsector2</Subsector>
</Subsectors>
</Sector>
<Sector SectorName="SectorName2">
<Subsectors>
<Subsector>Subsector1</Subsector>
<Subsector>Subsector2</Subsector>
</Subsectors>
</Sector>
</Sectors>
</Document>
Output:
EDIT
Since the XML structure cannot be changed, this new class will preserve the structure and also allow you to get the value in question. XmlText returns everything inside the value so a custom set had to be used to ensure that the whitespace was correctly trimmed from it.
[XmlRoot("Document")]
public class MetaDataXml
{
[XmlArray("Sectors")]
[XmlArrayItem("Sector")]
public Sector[] Sectors { get; set; }
}
[XmlRoot("Sector")]
public class Sector
{
[XmlIgnore]
private string _sectorName;
[XmlText]
public string SectorName
{
get
{
return _sectorName;
}
set
{
_sectorName = value.Trim();
}
}
[XmlArray]
[XmlArrayItem(ElementName = "Subsector")]
public List<string> Subsectors { get; set; }
}
Sample Program:
class Program
{
static void Main(string[] args)
{
var path = #"D:\sandbox\DocumentXml\DocumentXml\Sample.xml";
using (var stream = File.OpenRead(path))
{
var deserializer = new XmlSerializer(typeof(MetaDataXml));
var data = (MetaDataXml)deserializer.Deserialize(stream);
foreach (var s in data.Sectors)
{
Console.WriteLine($"Sector Name: {s.SectorName}");
foreach (var ss in s.Subsectors)
{
Console.WriteLine($"Subsector Name: {ss}");
}
Console.WriteLine();
}
}
Console.ReadKey();
}
}
I need to save multiple fields from an XML into different arrays.
This is what my XML looks like:
<Content>
<Colours>
<Colour name="Strong Red">
<R>255</R>
<G>0</G>
<B>0</B>
<A>255</A>
</Colour>
</Colours>
<Textures>
<Texture name="Character01">
<Path>Path/Folder</Path>
</Texture>
</Textures>
</Content>
Now everything was working fine when <Colours> was my root and i only added colours into one Array.
Now i want to add Textures and later more through the same XML file, thus moving the root one up to <Content>.
This is what my ColourLoader Class looked like with only Colours and <Colour> being the root of my XML:
[Serializable()]
[XmlRoot("Colours")]
public class ColourLoader
{
[XmlElement("Colour")]
public CustomColour[] Colours;
public static ColourLoader Load(string path)
{
var serializer = new XmlSerializer(typeof(ColourLoader));
using (var stream = new FileStream(path, FileMode.Open))
{
return serializer.Deserialize(stream) as ColourLoader;
}
}
}
My CustomColour class works fine, it uses [XmlElement("R")] etc. to read the values from the XML. It's just that i don't know how to read elements from a nested XML.
I somehow have to skip <Content> and add Colours from <Colours> as root and do the same for <Textures> etc.
I don't want to create multiple XML files as i would like to keep all content managing into one spot and only load an XML file once.
I think this is what you're after. I've also included a method that serializes the object. I find this very helpful in diagnosing idiosyncratic issues with XML Serialization...
Please vote as answer if this solved your issue.
[Serializable()]
[XmlRoot("Content")]
public class Content
{
[XmlArray("Colours")]
[XmlArrayItem("Colour")]
public CustomColour[] Colours { get; set; }
[XmlArray("Textures")]
[XmlArrayItem("Texture")]
public CustomTexture[] Textures { get; set; }
}
[Serializable()]
[XmlRoot("Colour")]
public class CustomColour
{
[XmlAttribute("name")]
public string Name { get; set; }
[XmlElement("R")]
public int R { get; set; }
[XmlElement("G")]
public int G { get; set; }
[XmlElement("B")]
public int B { get; set; }
[XmlElement("A")]
public int A { get; set; }
}
[Serializable()]
[XmlRoot("Texture")]
public class CustomTexture
{
[XmlAttribute("name")]
public string Name { get; set; }
[XmlElement("Path")]
public string Path { get; set; }
}
public static class ContentLoader
{
public static Content Load(TextReader textReader)
{
var serializer = new XmlSerializer(typeof(Content));
var ret = serializer.Deserialize(textReader) as Content;
return ret;
}
public static void Save(TextWriter textWriter, Content content)
{
var serializer = new XmlSerializer(typeof(Content));
serializer.Serialize(textWriter, content);
}
}
public static void XmlSerializing()
{
var xml = #"<?xml version=""1.0"" encoding=""utf-16""?>
<Content xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"">
<Colours>
<Colour name=""Strong Red"">
<R>255</R>
<G>0</G>
<B>0</B>
<A>255</A>
</Colour>
</Colours>
<Textures>
<Texture name=""Character01"">
<Path>Path/Folder</Path>
</Texture>
</Textures>
</Content>";
var reader = new StringReader(xml);
var content = ContentLoader.Load(reader);
Console.WriteLine("Deserialized version:");
Console.WriteLine(" Colours");
foreach (var colour in content.Colours)
{
Console.WriteLine(" R: {0}, G: {1}, B: {2}, A: {3}", colour.R, colour.G, colour.B, colour.A);
}
Console.WriteLine(" Textures");
foreach (var texture in content.Textures)
{
Console.WriteLine(" Path: {0}", texture.Path);
}
var contentObj = new Content()
{
Colours = new[] { new CustomColour() { Name = "StrongRed", R = 255, G = 0, B = 0, A = 255 } },
Textures = new[] { new CustomTexture() { Name = "Character01", Path = "Path/Folder" } }
};
Console.WriteLine(string.Empty);
Console.WriteLine("Serialized version:");
var writer = new StringWriter();
ContentLoader.Save(writer, contentObj);
Console.WriteLine(writer);
}
Is it possible to deserialize part of a binary file?
Basically I have an object similar to below, which I serialize into a binary file.
public class MyObject
{
public string Name { get; set; }
public int Value { get; set; }
public IList<MyOtherObject> { get; set; } // lots of data in here (order of kB-MB)
}
What I would like is to be able to deserialize only Name and Value by way of populating a ListView for file selection purposes and then deserialize the rest of the file when needed (i.e. the user chooses that file from the ListView).
As always, any help greatly appreciated and if any 3rd party libraries are suggested they would need to be able to be used freely in a commercial environment.
protobuf-net can do that, because it is not tied to the specific type; for example:
using ProtoBuf;
using System.Collections.Generic;
using System.IO;
[ProtoContract]
public class MyOtherObject { }
[ProtoContract]
public class MyObject
{
[ProtoMember(1)]
public string Name { get; set; }
[ProtoMember(2)]
public int Value { get; set; }
[ProtoMember(3)]
public IList<MyOtherObject> Items { get; set; }
}
[ProtoContract]
public class MyObjectLite
{
[ProtoMember(1)]
public string Name { get; set; }
[ProtoMember(2)]
public int Value { get; set; }
}
static class Program
{
static void Main()
{
var obj = new MyObject
{
Name = "abc",
Value = 123,
Items = new List<MyOtherObject>
{
new MyOtherObject(),
new MyOtherObject(),
new MyOtherObject(),
new MyOtherObject(),
}
};
using (var file = File.Create("foo.bin"))
{
Serializer.Serialize(file, obj);
}
MyObjectLite lite;
using (var file = File.OpenRead("foo.bin"))
{
lite= Serializer.Deserialize<MyObjectLite>(file);
}
}
}
But if you don't want two different types, and/or you don't want to have to add attributes - that can be done too:
using ProtoBuf.Meta;
using System.Collections.Generic;
using System.IO;
public class MyOtherObject { }
public class MyObject
{
public string Name { get; set; }
public int Value { get; set; }
public IList<MyOtherObject> Items { get; set; }
}
static class Program
{
static readonly RuntimeTypeModel fatModel, liteModel;
static Program()
{
// configure models
fatModel = TypeModel.Create();
fatModel.Add(typeof(MyOtherObject), false);
fatModel.Add(typeof(MyObject), false).Add("Name", "Value", "Items");
liteModel = TypeModel.Create();
liteModel.Add(typeof(MyOtherObject), false);
liteModel.Add(typeof(MyObject), false).Add("Name", "Value");
}
static void Main()
{
var obj = new MyObject
{
Name = "abc",
Value = 123,
Items = new List<MyOtherObject>
{
new MyOtherObject(),
new MyOtherObject(),
new MyOtherObject(),
new MyOtherObject(),
}
};
using (var file = File.Create("foo.bin"))
{
fatModel.Serialize(file, obj);
}
MyObject lite;
using (var file = File.OpenRead("foo.bin"))
{
lite = (MyObject)liteModel.Deserialize(
file, null, typeof(MyObject));
}
}
}
How about putting the Name and Valueinto a superclass and serializing them separately?
Alternatively, you could maintain a Dictionary and serialize that into one file.