My task was to serialize and deserialize an object.
I want to know:
Whether my object is serialized in the way I'm doing it
How I get to know that my object is being serialized or deserialized
Instead of passing the object in the Serialize Method, I am passing object.properties. Does this affect it in any way?
FileStream fs = new FileStream(#"D:\Rough Work\Serialization\Serialization\bin\Debug\Log.txt",FileMode.OpenOrCreate);
Laptop obj = new Laptop();
obj.Model = 2;
obj.SerialNumber = 4;
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(fs, obj.Model);
formatter.Serialize(fs, obj.SerialNumber);
[Serializable]
class Laptop
{
public int Model;
public int SerialNumber;
}
If you can successfully deserialize an object then you serialized it correctly.
You don't need to serialize the properties individually. You can just serialize the entire object and deserialize it the same way.
using (var fs = new FileStream(#"D:\Rough Work\Serialization\Serialization\bin\Debug\Log.txt",FileMode.OpenOrCreate))
{
var formatter = new BinaryFormatter();
formatter.Serialize(fs, obj);
}
using (var fs = new FileStream(#"D:\Rough Work\Serialization\Serialization\bin\Debug\Log.txt",FileMode.OpenOrCreate))
{
var formatter = new BinaryFormatter();
obj = formatter.Deserialize(fs) as Laptop;
}
If your question is how would Laptop class know that it is being serialized then you might want to implement ISerializable interface.
See BinaryFormatter.Deserialize
You can convert to serialised method to a string and output it to the debug window
I want to know:
Whether my object is serialized in the way I'm doing it
Then you can use xml serialization, that way you can check your serialized object since it will be in human-readable form.
Related
Here is a short code that works fine with BinaryFormatter and does not work properly with SoapFormatter:
[Serializable]
public class CustomDictionary : Dictionary<int, object>
{
public CustomDictionary() { }
protected CustomDictionary(SerializationInfo info, StreamingContext context) : base(info, context) { }
}
var input = new CustomDictionary();
input.Add(1, new Address("NYC", "Gold street", 17));
input.Add(2, "mystring");
input.Add(3, new Being("Serge"));
IFormatter formatter = new SoapFormatter(); // works fine with BinaryFormatter() here
FileStream s = new FileStream("test.data", FileMode.Create);
formatter.Serialize(s, input);
s.Close();
FileStream s2 = new FileStream("test.data", FileMode.Open);
var output = (CustomDictionary)formatter.Deserialize(s2);
s2.Close();
Here, Being and Address are serializable classes. I basically want to be able to put any kind of objects as values in my custom dictionary.
If I use the SoapFormatter, after deserialization, values at index 1 and 3 are null in output (the recreated custom dictionary).
It seems to me that BinaryFormatter stores the type of the objects while the SoapFormatter does not.
Am I missing something?
Is there any way to have the same behaviour with the SoapFormatter than with the BinaryFormatter?
Thank you,
For I can have direct access to a particular object in a serialized generic list, I need to know position of it from de-serialized stream.
private static void Serialze(object obj, FileStream Stream)
{
BinaryFormatter bin = new BinaryFormatter();
bin.FilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Low;
bin.Serialize(Stream, obj);
}
private static object DeSerialize(FileStream Stream)
{
if (Stream.Position >= Stream.Length) return null;
BinaryFormatter bin = new BinaryFormatter();
bin.FilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Low;
object x = bin.Deserialize(Stream);
return x;
}
Suppose I have a generic list like this:
List<MyClass> L1=new List<MyClass>();
How can I to find position of L1[10] in my FileStreem, for using it, in DeSerialize method?
The format that BinaryFormatter uses is not seekable. You cannot extract sub-objects.
Probably, this question is an instance of the XY-Problem. Tell us what you want to achieve and why you need this. As asked, there is no answer.
Maybe you can make use of a database instead. Or, use Protocol Buffers, which are more flexible.
Using binary formatting for 1st time in .net C#
Code from MSDN is like this:
IFormatter formatter = new BinaryFormatter();
Stream stream = new FileStream("MyFile.lvl", FileMode.Create, FileAccess.Write,FileShare.None);
formatter.Serialize(stream, Globals.CurrentLevel);
stream.Close();
Just wondering should I store an IFormatter in a field in my class and use it over and over again or should I do as above and instantiate a new one every time I save/load something?
I noticed it is not IDisposable.
There's very little overhead in re-creating a BinaryFormatter, most of the properties it sets in the constructor are enums, see here (thanks to Reflector):
public BinaryFormatter()
{
this.m_typeFormat = FormatterTypeStyle.TypesAlways;
this.m_securityLevel = TypeFilterLevel.Full;
this.m_surrogates = null;
this.m_context = new StreamingContext(StreamingContextStates.All);
}
If you were going to re-use it though, you'd need to synchronize access to the Serialize and Deserialize methods to keep them thread-safe.
I want to be able to send a XmlSerializer class (which is generated obvious in remote C# application) over a WebService that will then deserialize it into a class. (I didnt know it its possible either)
My class is:
SystemInfo
I'm serializing it this way:
XmlSerializer mySerializer = new XmlSerializer(typeof(SystemInfo));
StreamWriter myWriter = new StreamWriter(textBox1.Text);
mySerializer.Serialize(myWriter, sysinfo);
How can i build the WebService?
[WebMethod]
public void Reports(XmlSerializer xmlSerializer)
{
.
.
.
}
Can anyone help me out?
Regards
First I assume you want to pass arbitrary types to a single web method, where the types are shared by the client and the server.
There is not much point in sending the XmlSerializer, it only has the logic to serialize/deserialize. It does not have the actual data, that is either read/written to a stream. What you should do is pass either a string or and XmlNode.
The caller of the web service can then a client side instance of XmlSerializer and serialize the object to a string, then call the web method passing the string as an argument. The web method it self can then create an instance of a XmlSerializer and deserialize the string back into an object. Of course to create the server size instance of the serializer you will need to know the root type to create the serializer for, you can pass this as a type name and use Type.GetType() to get the correct type to pass to the XmlSerializer.
If you know upfront which types you are going to be passing then you could also declare your web method more strongly typed and explicitly create methods for the types you expect to recieve.
If the wire format is not too much of a concern, you could also user SoapFormatter or a BinaryFormatter to handle the serialization/deserialization. In the later case of the BinaryFormatter you would declare your web method to take a byte[] argument, the advantage of these formatters (serializers) is that they do not need additional info on the type when you create the instance of the formatter, but they can be slower than an XmlSerializer
Update: Added some simple examples (Untested)
Example using an XmlSerializer, here you will need to pass the type name from the client side, so I made it an additional argument.
[WebMethod]
public void Reports(string xml, string typeName)
{
XmlSerializer xs = new XmlSerializer(Type.GetType(typeName));
object obj = xs.Deserialize(new StringReader(xml));
// use the deserialize object
}
Example using a BinaryFormatter, no type name needed but you the class types will need to be serializable
[WebMethod]
public void Reports(byte[] data)
{
BinaryFormatter bf = new BinaryFormatter();
object obj = bf.Deserialize(new MemoryStream(data));
// use the deserialized object
}
On the client side you would use something like the following to serialize using the BinaryFormatter.
// initialize the SystemInfo instance that you want to pass to the server
SystemInfo si = new SystemInfo() { SystemName = "My System" };
// Serialize to a memory stream
BinaryFormatter bf = new BinaryFormatter();
MemoryStream ms = new MemoryStream();
bf.Serialize(ms, si);
// Call the service, passing the array from the memory stream
ws.Reports(ms.ToArray());
Chris, thanks for helping me out. It was a major step forward.
I solved the problem sending the xml string:
SystemInfo sysinfo = new SystemInfo();
sysinfo.RUN();
XmlSerializer mySerializer = new XmlSerializer(typeof(SystemInfo));
MemoryStream memStream = new MemoryStream();
mySerializer.Serialize(memStream, sysinfo);
memStream.Seek(0, System.IO.SeekOrigin.Begin);
XmlDocument doc = new XmlDocument();
doc.Load(memStream);
memStream.Close();
localhost.WS_Agente dasdsa = new localhost.WS_Agente();
dasdsa.Reports(doc.InnerXml);
And the WebService:
[WebMethod]
public void Reports(string xml)
{
XmlSerializer mySerializer = new XmlSerializer(typeof(SystemInfo));
SystemInfo obj = (SystemInfo)mySerializer.Deserialize(new StringReader(xml));
}
Its working like a charm now :)
My question is: Can i improve the code?
Thanks
Presently I need to serialize one of my object which contains more my own classes object.
But the problem is I dont want to save it in a file and then retrieve it into memory stream.
Is there any way to directly serialize my object into stream.
I used BinaryFormatter for seializing.
First I used a MemoryStream directly to take serialize output but it is giving error
at time of deserialization. But later when I serialize it with a file then close it and
again reopen it , it works perfectly. But I want to take it direct into stream because
in my program I need to do it frequently to pass it into network client. And using file
repeatedly might slow down my software.
Hope I clear my problem. Any Sugetion ?
If you're trying to deserialize from the same MemoryStream, have you remembered to seek back to the beginning of the stream first?
var foo = "foo";
var formatter = new BinaryFormatter();
using (var stream = new MemoryStream())
{
// Serialize.
formatter.Serialize(stream, foo);
// Deserialize.
stream.Seek(0, SeekOrigin.Begin);
foo = formatter.Deserialize(stream) as string;
}
Here's a quick and dirty sample, of serializing back and forth a string. Is this what your trying to do?
static void Main(string[] args)
{
var str = "Hello World";
var stream = Serialize(str);
stream.Position = 0;
var str2 = DeSerialize(stream);
Console.WriteLine(str2);
Console.ReadLine();
}
public static object DeSerialize(MemoryStream stream)
{
BinaryFormatter formatter = new BinaryFormatter();
return formatter.Deserialize(stream);
}
public static MemoryStream Serialize(object data)
{
MemoryStream streamMemory = new MemoryStream();
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(streamMemory, data);
return streamMemory;
}