How can I create a deep clone without using 'BinaryFormatter'? - c#

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.

Related

Serialize a non-serializable custom object from a nuget package and store it in SQLite database

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.

convert dictionary or list to byte[]

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.

Serializing and deserializing a List<List<object>> with BinaryFormatter

Let's say I have
List<object> mainList = new List<object>();
And it contains
List<string> stringList = new List<string();
List<CustomClass> custList = new List<CustomClass>();
mainList.Add(stringList);
mainList.Add(custList);
To serialize
Stream stream;
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, mainList);
To deserialize
Stream stream = (Stream)o;
BinaryFormatter formatter = new BinaryFormatter();
List<object> retrievedList = (List<object>)formatter.Deserialize(stream);
At this point, I receive an error that the stream read (deserialization) reached the end of the stream without retrieving a value.
Do I need to specify something besides...
[Serializable]
public class CustomClass { .... }
in the custom class to make this work? Can I not deserialize a List> that contains different type of object every time?
I tried
IList list = (IList)Activator.CreateInstance(typeof(custClassList[0]))
and tried to send and receive this, but got the same issue.
I can however serialize and deserialize a specified type or List, but I really need it to be dynamic.
Basically, BinaryFormatter is a joke. It works in some cases, but will fail in almost identical scenarios for unknown reasons.
The best and superior alternative to BinaryFormatter is the third-party library protobuf-net (https://github.com/mgravell/protobuf-net), developed by Marc Gravel.
This beauty solved all the problems I was having in one pass. It's much easier to set up and reacts more perfectly to complex, custom classes.
I should also mention that it's faster, in the terms of de/serialization.
In order to fix the issue that causes the error "stream read (deserialization) reached the end of the stream ", the stream position needs to reset to 0 as follows...
stream.Position = 0;
Do I need to specify something besides...
[Serializable] public class CustomClass { .... }
Nope...That should be good for what you are doing.
in the custom class to make this work? Can I not deserialize a List>
that contains different type of object every time?
You should be able to serialize any object.

How to save a serializable object using File.WriteAllBytes?, C#

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

Way to Deserialize JSON from HttpWebResponse without 3rd party frameworks

I'm trying to keep from depending on open source or third party libraries such as Json.NET to parse incoming JSON from an HttpWebResponse. Why? Because the more reliance on open source frameworks to aid in your implementations, the more your app has to rely on those dependencies...I don't like my apps to be depenent on a lot of libraries for many reasons if at all possible. I'm ok with using stuff like Enterprise Library because it's supported by MS but I'm taking more open source libraries.
Anyway, I'm trying to figure out the best way to parse incoming JSON server-side in .NET 3.5.
I know this is going to get a lot of responses and I've even used the .NET 3.5 JavaScriptSerializer to serialize data to JSON but now I'm trying to figure out the best and most simple way to do the reverse without again, having to use a 3rd party / open source framework to aid in this.
The Microsoft recommended JSON serializer is DataContractJsonSerializer This class exists within the System.Runtime.Serialization assembly
The sample demonstrates deserializing from JSON data into an object.
MemoryStream stream1 = new MemoryStream();
Person p2 = (Person)ser.ReadObject(stream1);
To serialize an instance of the Person type to JSON, create the DataContractJsonSerializer first and use the WriteObject method to write JSON data to a stream.
Person p = new Person();
//Set up Person object...
MemoryStream stream1 = new MemoryStream();
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(Person));
ser.WriteObject(stream1, p);
Update: Added Helper class
Here is a sample helper class that you can use for simple To/From Json serialization:
public static class JsonHelper
{
public static string ToJson<T>(T instance)
{
var serializer = new DataContractJsonSerializer(typeof(T));
using (var tempStream = new MemoryStream())
{
serializer.WriteObject(tempStream, instance);
return Encoding.Default.GetString(tempStream.ToArray());
}
}
public static T FromJson<T>(string json)
{
var serializer = new DataContractJsonSerializer(typeof(T));
using (var tempStream = new MemoryStream(Encoding.Unicode.GetBytes(json)))
{
return (T)serializer.ReadObject(tempStream);
}
}
}

Categories