I have a bit of C# code which I use for performing a deep copy of an object:
public static T Copy<T>(T objectToCopy)
{
T result = default(T);
using (var memoryStream = new MemoryStream())
{
var formatter = new BinaryFormatter();
formatter.Serialize(memoryStream, objectToCopy);
memoryStream.Seek(0, SeekOrigin.Begin);
result = (T)formatter.Deserialize(memoryStream);
memoryStream.Close();
}
return result;
}
I get this warning from Visual Studio:
Warning SYSLIB0011
'BinaryFormatter.Serialize(Stream)' is obsolete: 'BinaryFormatter serialization is obsolete and should not be used. See https://aka.ms/binaryformatter for more information.'
I get the same warning about BinaryFormatter.Deserialize(Stream).
I've looked at the suggested link, and they list some preferred alternatives:
XmlSerializer and DataContractSerializer to serialize object graphs into and from XML. Do not confuse DataContractSerializer with NetDataContractSerializer.
BinaryReader and BinaryWriter for XML and JSON.
The System.Text.Json APIs to serialize object graphs into JSON.
I'm just struggling to figure out in my specific case how I would implement one of those alternatives.
If anyone could assist me in this I would greatly appreciate it.
Thank you.
I'm working with some highly custom objects from a nuget package that I need to store in the local SQLite db using Xamarin. I tried using this code
public static byte[] Serialize(ComplexType c)
{
byte[] arrayData;
using(MemoryStream stream = new MemoryStream())
{
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize( stream, c );
arrayData = stream.ToArray();
stream.Close();
}
return arrayData;
}
public static ComplexType Deserialize(byte[] arrayData)
{
ComplexType c;
using(MemoryStream stream = new MemoryStream())
{
stream.Write( arrayData, 0, arrayData.Length );
stream.Seek( 0, SeekOrigin.Begin );
BinaryFormatter formatter = new BinaryFormatter();
c = (ComplexType) formatter.Deserialize( stream );
}
return c;
}
to serialize and store the object then retrieve it and deserialize it. It seems like it worked fine to do the serialization but now it turns out that the object is not marked serializable. I can't add the SerializableAttribute property to it because it's from a nuget. I tried editing the object definition in the nuget but of course it's locked.
Is there any easy way to pull off serializing an object not marked serializable or perhaps some other simple method of storing a non-serializable custom object in a SQLite database? Or should I just byte the bullet and write really complicated setters and getters to store all of the custom object's individual custom properties broken down into their individual lists of standard properties and basically deconstruct and reconstruct the object every time it goes to and from the database?
I'm seeing mixed reports on ISerializable and derived classes. Will implementing ISerializable on a derived class from the custom object allow the derived class to be serialized? What about IXMLSerializable? Will either of these work? I just want to get some clarification if possible before I go way down the wrong rabbit hole.
Ok, i've seen many similar questions both on here and unity forums asking about converting from one format to another. I've got a (hopefully) simple question that i just can't find the answer for. I'm using the game-center plugin from Prime31 to handle a turn based multi-player game. Inside the plugin for Prime31 they ask you for a byte[] to send to the other players. (State data) So the question is, what would be a good way to convert a List to a byte array AND then convert them back from byte array?
for reference this is as complicated a class as i need, i might need to add more members later, but not any different types. ALSO the list of int's(cards in hand) could easily be 4 separate int if that makes converting the list of PokerPlayers to an byte[] any easier. Also at this list is not a set length but will always be 4-8.
public class PokerPlayer{
public string playerID;
public string alias;
public int wildCard;
public List<int> cardsInHand;
public int chips;
}
I feel like the when i see the answer I'm going to smack myself for not seeing the answer sooner. Any pointers/ links to relevant materials would be sweet, i've searched google for a good 3 hours now with similar (SO similar) but not quite the same questions.
You may want to try serialization.
var binFormatter = new BinaryFormatter();
var mStream = new MemoryStream();
binFormatter.Serialize(mStream, myObjToSerialize);
//This gives you the byte array.
mStream.ToArray();
And then if you want to turn the byte array back into an object:
var mStream = new MemoryStream();
var binFormatter = new BinaryFormatter();
// Where 'objectBytes' is your byte array.
mStream.Write (objectBytes, 0, objectBytes.Length);
mStream.Position = 0;
var myObject = binFormatter.Deserialize(mStream) as YourObjectType;
Update:
Microsoft warns about using BinaryFormatter because it is "insecure and can't be made secure".
Please read aka.ms/binaryformatter for more details.
Preferred alternatives
.NET offers several in-box serializers that can handle untrusted data safely:
XmlSerializer and DataContractSerializer to serialize object graphs into and from XML. Do not confuse DataContractSerializer with NetDataContractSerializer.
BinaryReader and BinaryWriter for XML and JSON.
The System.Text.Json APIs to serialize object graphs into JSON.
BinaryFormatter is now a security risk. If I find a good way to do this without using it I'll be back
https://learn.microsoft.com/en-us/dotnet/core/compatibility/core-libraries/5.0/binaryformatter-serialization-obsolete
Edit:
This is still the top result in Google so I'll show what I've done to move away from BinaryFormatter
You need Newtonsoft.Json
public static class ExtendedSerializerExtensions
{
private static readonly JsonSerializerSettings SerializerSettings = new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Auto,
};
public static byte[] Serialize<T>(this T source)
{
var asString = JsonConvert.SerializeObject(source, SerializerSettings);
return Encoding.Unicode.GetBytes(asString);
}
public static T Deserialize<T>(this byte[] source)
{
var asString = Encoding.Unicode.GetString(source);
return JsonConvert.DeserializeObject<T>(asString);
}
}
It's not very far to go from here if you need a stream rather than a byte array
Converting data into byte stream (and back) is called serialization (and deserialization).
You can use the BinaryFormatter class to do so.
I need to save an object, its serializable but I donot want to use XML.
Is it possible to write the raw bytes of the object and then read it off the disk to create the object again?
Thanks for the help!
Use a BinaryFormatter:
var formatter = new BinaryFormatter();
// Serialize
using (var stream = File.OpenWrite(path))
{
formatter.Serialize(stream, yourObject);
}
...
// Deserialize
using (var stream = File.OpenRead(path))
{
YourType yourObject = (YourType)formatter.Deserialize(stream);
}
Yes, it is called binary serialization. There are some good examples on the MSDN site:
http://msdn.microsoft.com/en-us/library/4abbf6k0(v=vs.100).aspx
I created a binary serialized file of my object, so that I could use it as a database file for many other projects. It works quite fine with the same project, but when I try to deserialize that file from other projects, it won't. The error that appears says, "xxxx.xxxx assembly not found". So, how should I serialize the object in order to make it assembly independent???
Here's my code :
// Binary formatter
IFormatter formatter = new BinaryFormatter();
Stream stream = new FileStream("BinarySerialization.bin",
FileMode.Create,
FileAccess.Write, FileShare.None);
formatter.Serialize(stream, words);
stream.Close();
What amendments do I need to do??? Please provide me with a working code example/sample.
Thanks.
BinaryFormatter is a type-based serialized; it deeply embeds type metadata into the output. I would wager that you have copied the class definition between the projects - that isn't enough for BinaryFormatter, since that is no longer the same Type (types are bound to their assembly).
In your scenario, it sounds to me that the correct thing to do here would be to use a contract-based serializer; for example:
xml (XmlSerializer, DataContractSerializer, etc)
json (JavascriptSerializer, JSON.net, etc)
binary (protobuf-net, etc)
There would would entirely in your scenario, and would also have much better version tolerance (BinaryFormatter is very brittle with versions)
You mention "XMLs aren't safe here, as I don't want the users to know the contents of the main database file." - in that case protobuf-net has the "advantage" of being not human-readable, but note: none of these, nor BinaryFormatter are encrypted; if I wanted to, I could obtain the contents if I really, really wanted to. If you need strong security, use proper encryption. In which case your code becomes (in addition to maybe a few marker attributes):
using(var stream = new FileStream("BinarySerialization.bin", FileMode.Create,
FileAccess.Write, FileShare.None))
{
Serializer.Serialize(stream, words);
}
Edit to show (per comments) how to serialize Dictionary<string, List<Word>> where Word is a class with 2 string members (most of the code here is just plumbing to show a complete example):
using System;
using System.Collections.Generic;
using System.IO;
using ProtoBuf;
[ProtoContract]
public class Word {
[ProtoMember(1)]
public string Foo { get; set; }
[ProtoMember(2)]
public string Bar { get; set; }
}
static class Program {
public static void Main() {
var data = new Dictionary<string, List<Word>>{
{"abc", new List<Word> {
new Word { Foo = "def", Bar = "ghi"},
new Word { Foo = "jkl", Bar = "mno"}
}},
{"pqr", new List<Word> {
new Word {Foo = "stu", Bar = "vwx"}
}}
};
using(var file = File.Create("my.bin")) {
Serializer.Serialize(file, data);
}
Dictionary<string, List<Word>> clone;
using(var file = File.OpenRead("my.bin")) {
clone = Serializer.Deserialize<
Dictionary<string, List<Word>>>(file);
}
foreach(var pair in clone) {
Console.WriteLine(pair.Key);
foreach(var word in pair.Value){
Console.WriteLine("\t{0} | {1}", word.Foo, word.Bar);
}
}
}
}
I would put all my models that have to be serialized into a seperate assembly.
Then you reference this assembly everywhere you need to deserialize the Models.
If not you need some kind of generator, that recreates the models based on some schema (same as WCF does with its utilities) or use plain formats like XML to persist your data.
The serialization mechanism in .NET creates a helper dll out of the type to serialize and deserialize your data in runtime. First it will spit out a code file that gets compiled and then the helper dll is loaded to do the serialization and deserialization.
If for some reason something happens while the helper .dll gets created - let's say a compilation error- then the runtime will not found this dll.
If the dll name in your case is some random character then I would say you are facing the problem described above. You can troubleshoot this by switching on an undocument switch. See the following article:
HOW TO: Debug into a .NET XmlSerializer Generated Assembly