I'm trying to set up an interface to send serialized objects between a client and a server using a TCP connection.
I have the following class and extension methods for reading and writing these objects from/to the stream:
public class NetworkTransmittedUpdate
{
/// <summary>
/// The type of update that is being sent
/// </summary>
public UpdateType UpdateType { get; init; }
/// <summary>
/// The type that UpdateObject should be deserialized as. Should match one of the types in SerializedTypes
/// </summary>
public string UpdateObjectType { get; init; } = string.Empty;
/// <summary>
/// Any information that accompanies the update. Each update type has an associated UpdateObject type, which is
/// usually but not always the same for both frontend and backend. UpdateObject may be null if only the event
/// happening must be conveyed.
/// </summary>
public object? UpdateObject { get; init; }
}
public static class StreamExtensions
{
/// <summary>
/// Attempts to read a serialized object from the stream, convert it, and return it
/// </summary>
/// <param name="stream">The stream to read from</param>
/// <typeparam name="T">The type of object to deserialize</typeparam>
/// <returns>An instance of the object, or null if it could not be created</returns>
public static T? ReadObject<T>(this Stream stream) where T : class
{
// Get length of incoming object
var sizeBuffer = new byte[sizeof(int)];
var bytesRead = 0;
Debug.Assert(stream.CanRead);
while (bytesRead < sizeBuffer.Length)
bytesRead += stream.Read(sizeBuffer, bytesRead, sizeBuffer.Length - bytesRead);
// Create a buffer for serialized data
var serializationLength = BitConverter.ToInt32(sizeBuffer);
var serializedDataBuffer = new byte[serializationLength];
// Get data from the stream
bytesRead = 0;
while (bytesRead < serializationLength)
bytesRead += stream.Read(serializedDataBuffer, bytesRead, serializationLength - bytesRead);
// Deserialize data into an object
var json = Encoding.UTF8.GetString(serializedDataBuffer);
// Deserialize the wrapped type correctly using reflection
var deserializedObject = JsonSerializer.Deserialize<T>(json);
if (deserializedObject is NetworkTransmittedUpdate {UpdateObject: { }} dynamicUpdateWrapper)
{
// In this block, we know we are wrapping data. The deserializer doesn't choose the write type by default, so we need to create a new
var innerData = dynamicUpdateWrapper.UpdateObject!.ToString();
var innerDataType = Type.GetType(dynamicUpdateWrapper.UpdateObjectType);
return new NetworkTransmittedUpdate
{
UpdateType = dynamicUpdateWrapper.UpdateType,
UpdateObjectType = dynamicUpdateWrapper.UpdateObjectType,
UpdateObject = JsonSerializer.Deserialize(innerData ?? string.Empty, innerDataType!)
} as T;
}
return deserializedObject;
}
/// <summary>
/// Serializes and writes an object to a stream
/// </summary>
/// <param name="stream">The stream to write UTF-8 data to</param>
/// <param name="value">An object to serialize and write</param>
/// <typeparam name="T">A serializable type</typeparam>
public static void WriteObject<T>(this Stream stream, T value)
{
var json = JsonSerializer.Serialize(value);
var bytes = Encoding.UTF8.GetBytes(json);
// Always send a number of bytes ahead, so the other side knows how much to read
stream.Write(BitConverter.GetBytes(bytes.Length));
// Send serialized data
stream.Write(bytes);
stream.Flush();
}
}
For some reason, the below test gets stuck while reading the length of object being sent.
[Fact]
public void TestChatMessageNetworkPackets()
{
// Setup
var listener = new TcpListener(IPAddress.Any, 12321);
listener.Start();
using var client = new TcpClient("localhost", 12321);
using var server = listener.AcceptTcpClient();
using var clientStream = client.GetStream();
using var serverStream = server.GetStream();
// Send and receive chat message
clientStream.WriteObject(new NetworkTransmittedUpdate()
{
UpdateObject = new string("Test message"),
UpdateType = UpdateType.ChatMessage,
UpdateObjectType = typeof(string).FullName!
});
var update = clientStream.ReadObject<NetworkTransmittedUpdate>();
}
Change this:
var update = clientStream.ReadObject<NetworkTransmittedUpdate>();
To this:
var update = serverStream.ReadObject<NetworkTransmittedUpdate>();
You want to write on the Client stream, then read on the Server stream since that's on the other side of the fence.
Related
I ran into an issue recently when in an existing Console Application project we're forced to remove a reference to WSE 3.0. When I tried to remove it from references (because I could not find where it's used) it turned out there is only one place and it's using the SoapEnvelope class.
A little bit about the application: it's a console application that connects to an Exchange Server and listens to incoming emails, around 2-3k emails daily.
The SoapEnvelope class is used to read and parse the email body:
/// <summary>
/// Reads content of received HTTP request.
/// </summary>
/// <param name="client">The specified client.</param>
/// <returns>The watermark string if the read is successful; otherwise the last watermark.</returns>
public string Read(TcpClient client)
{
try
{
_myReadBuffer = new byte[client.ReceiveBufferSize];
using (var networkStream = client.GetStream())
{
var httpRequest = new MailboxHttpRequest(networkStream);
if (httpRequest.HasBody)
{
var httpResponse = new MailboxHttpResponse(_mailbox);
httpResponse.ParseBody(httpRequest.Body);
httpResponse.Send(networkStream, httpRequest.Body);
}
return httpRequest.Watermark;
}
}
catch (Exception ex)
{
Logger.WriteErrorLine("[EventsCollector] Error calling Read in MailboxNotificationManager", ex);
return _mailbox.LastWatermark;
}
finally
{
_myReadBuffer = null;
}
}
And the ParseBody methods looks like this:
/// <summary>
/// Parses the XML body content of receive notification and initialized email processing, if new message was received.
/// </summary>
/// <param name="body">XML content of received notification.</param>
public void ParseBody(string body)
{
var soapEnvelope = new SoapEnvelope() { InnerXml = body };
var serializer = new XmlSerializer(typeof(SendNotificationResponseType));
using (var reader = new XmlNodeReader(soapEnvelope.Body.FirstChild))
{
var notificationResponse = (SendNotificationResponseType)serializer.Deserialize(reader);
if (notificationResponse.ResponseMessages != null) // Process notification, if request contains response message
{
_result = processNotification(notificationResponse);
}
}
}
As you can see, it creates a SoapEnvelope class to access the body`s first child.
MailboxHttpRequest class
private class MailboxHttpRequest
{
private readonly Regex _httpRequestBodyLengthPattern = new Regex(#"Content-Length: (?<BodyLength>\d*)", RegexOptions.Compiled);
private readonly Regex _httpRequestBodyPattern = new Regex(#"<\?xml .*", RegexOptions.Compiled);
private readonly Regex _httpRequestWatermarkPattern = new Regex(#"<t:Watermark>(?<Watermark>.*?)<\/t:Watermark>", RegexOptions.Compiled);
private const int _bufferSize = 8192;
public bool HasBody
{
get { return !String.IsNullOrEmpty(Body); }
}
public string Body { get; private set; }
public string Watermark { get; private set; }
/// <summary>
/// Initializes a new instance of the <see cref="MailboxHttpRequest"/> class and reads incoming messages
/// </summary>
/// <param name="networkStream">The network stream.</param>
public MailboxHttpRequest(NetworkStream networkStream)
{
var completeRequest = new StringBuilder();
var readBuffer = new byte[_bufferSize];
do // Read incoming message that might consist of many parts
{
var newDataLength = networkStream.Read(readBuffer, 0, readBuffer.Length);
completeRequest.Append(Encoding.ASCII.GetString(readBuffer, 0, newDataLength));
}
while (networkStream.DataAvailable || !requestWasFullyReceived(completeRequest.ToString()));
Body = _httpRequestBodyPattern.Match(completeRequest.ToString())
.Value;
Watermark = _httpRequestWatermarkPattern.Match(Body).Groups["Watermark"].Value;
}
}
The downside is that I`m not able test this part of code since I cant listen to same mailbox so I cant check what and how does the passed string look like.
If anybody has any suggestion on how to replace the SoapEnvelope class, would be greatly appreciate it.
Cosmin
So I am trying to deserialize and serialize a List.
The issue: The list(list1) is not saving to the file called "ListData" which should be created if not already there, into the documents folder in the android internal storage.
I think the file may not be creating properly or something, or the filepath is incorrect. Below is how it should be functioning but that isn't working as explained with the issue above.
I want to save the filename as something like "ListData".
Also, needs to be saved into the Internal Storage somewhere such as the Data folder of the app or Documents in internal storage.
The following is what i have for the code, but I can't seem to find any help elsewhere to fix my issue. It doesn't work, any ideas for a solution to what I want it to do?
Code:
public abstract class DataHandler
{
public static void SaveLists()
{
string filePath = Android.OS.Environment.DirectoryDocuments;
string fileName = "ListData";
XmlSerializer serializer = new XmlSerializer(typeof(List<Item>));
Stream writer = new FileStream(filePath, FileMode.Create);
serializer.Serialize(writer, _LISTFROMANOTHERCLASS_);
writer.Close();
}
public static void LoadLists()
{
string filePath = Android.OS.Environment.DirectoryDocuments;
string fileName = "ListData";
XmlSerializer serializer = new XmlSerializer(typeof(List<Item>));
Stream reader = new FileStream(filePath, FileMode.Open);
List<Item> list1 = new List<Item>();
list1 = (List<Item>) serializer.Deserialize(reader);
_LISTFROMANOTHERCLASS_ = list1;
reader.Close();
}
}
Hi I have written a class to do these but with JSON serlization check is it helps it uses MVVM Cross, It has code written to encrypt and decrypt data you can avoid these parts
public class PersistantStorageHelper<T>
{
IMvxFileStoreAsync _mvxFileStoreAsync;
IMvxFileStore _mvxFileStore;
EDEngine bcEngine = new EDEngine(new AesEngine(), Encoding.UTF8);
string currentkey_temp_dev = "AthulHarikumar00";//This static key is not being used it is a just a place holder
public PersistantStorageHelper() {
this._mvxFileStore = Mvx.Resolve<IMvxFileStore>();
this._mvxFileStoreAsync = Mvx.Resolve<IMvxFileStoreAsync>();
bcEngine.SetPadding(new Pkcs7Padding());
currentkey_temp_dev = Constants.PassPhrase.Substring(4, 12)+"Road";
}
/// <summary>
///
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public async Task<T> GetPersistantObject(T obj)
{
var fileName = (typeof(T).ToString().Replace(".", "_"));
var x= await GetPersistantObject(obj, fileName);
return x;
}
/// <summary>
/// If object exists returns the object else saves a plain object and returns it
/// </summary>
/// <param name="obj">empty placeholder object</param>
/// <returns>Filesystem object</returns>
public async Task<T> GetPersistantObject( T obj,string fileName) {
List<string> files = new List<string>(_mvxFileStore.GetFilesIn(_mvxFileStore.NativePath("")));
fileName = _mvxFileStore.NativePath(fileName);
if (!files.Contains(fileName))
{
var objJson = Newtonsoft.Json.JsonConvert.SerializeObject(obj);
objJson= bcEngine.Encrypt(objJson, currentkey_temp_dev);
await _mvxFileStoreAsync.WriteFileAsync(fileName,objJson);
}
else {
try
{
var temp = await _mvxFileStoreAsync.TryReadTextFileAsync(fileName);
var str = bcEngine.Decrypt(temp.Result, currentkey_temp_dev);
obj = Newtonsoft.Json.JsonConvert.DeserializeObject<T>(str);
}
catch(Exception e) {
var objJson = Newtonsoft.Json.JsonConvert.SerializeObject(obj);
objJson = bcEngine.Encrypt(objJson, currentkey_temp_dev);
await _mvxFileStoreAsync.WriteFileAsync(fileName, objJson);
}
}
return obj;
}
/// <summary>
///
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public async Task<T> SetPersistantObject(T obj)
{
var fileName = _mvxFileStore.NativePath(typeof(T).ToString().Replace(".", "_"));
var temp = await SetPersistantObject(obj, fileName);
return temp;
}
/// <summary>
/// Saves object to persistant storage with encryption
/// </summary>
/// <param name="obj">object to be stored</param>
/// <returns>Saved object</returns>
public async Task<T> SetPersistantObject(T obj,string fileName)
{
List<string> files = new List<string>(_mvxFileStore.GetFilesIn(_mvxFileStore.NativePath("")));
fileName = _mvxFileStore.NativePath(fileName);
var objJson = Newtonsoft.Json.JsonConvert.SerializeObject(obj);
objJson = bcEngine.Encrypt(objJson, currentkey_temp_dev);
await _mvxFileStoreAsync.WriteFileAsync(fileName, objJson);
return obj;
}
}
java.util.List is not serializable, but java.util.ArrayList is. So just change List to ArrayList on both sites (left before variablename and right for constructor). Also check if your Item implements Serializable
I have a list of objects and I need to save that somewhere in my computer. I have read some forums and I know that the object has to be Serializable. But it would be nice if I can get an example. For example if I have the following:
[Serializable]
public class SomeClass
{
public string someProperty { get; set; }
}
SomeClass object1 = new SomeClass { someProperty = "someString" };
But how can I store object1 somewhere in my computer and later retrieve?
I just wrote a blog post on saving an object's data to Binary, XML, or Json. You are correct that you must decorate your classes with the [Serializable] attribute, but only if you are using Binary serialization. You may prefer to use XML or Json serialization. Here are the functions to do it in the various formats. See my blog post for more details.
Binary
/// <summary>
/// Writes the given object instance to a binary file.
/// <para>Object type (and all child types) must be decorated with the [Serializable] attribute.</para>
/// <para>To prevent a variable from being serialized, decorate it with the [NonSerialized] attribute; cannot be applied to properties.</para>
/// </summary>
/// <typeparam name="T">The type of object being written to the binary file.</typeparam>
/// <param name="filePath">The file path to write the object instance to.</param>
/// <param name="objectToWrite">The object instance to write to the binary file.</param>
/// <param name="append">If false the file will be overwritten if it already exists. If true the contents will be appended to the file.</param>
public static void WriteToBinaryFile<T>(string filePath, T objectToWrite, bool append = false)
{
using (Stream stream = File.Open(filePath, append ? FileMode.Append : FileMode.Create))
{
var binaryFormatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
binaryFormatter.Serialize(stream, objectToWrite);
}
}
/// <summary>
/// Reads an object instance from a binary file.
/// </summary>
/// <typeparam name="T">The type of object to read from the binary file.</typeparam>
/// <param name="filePath">The file path to read the object instance from.</param>
/// <returns>Returns a new instance of the object read from the binary file.</returns>
public static T ReadFromBinaryFile<T>(string filePath)
{
using (Stream stream = File.Open(filePath, FileMode.Open))
{
var binaryFormatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
return (T)binaryFormatter.Deserialize(stream);
}
}
XML
Requires the System.Xml assembly to be included in your project.
/// <summary>
/// Writes the given object instance to an XML file.
/// <para>Only Public properties and variables will be written to the file. These can be any type though, even other classes.</para>
/// <para>If there are public properties/variables that you do not want written to the file, decorate them with the [XmlIgnore] attribute.</para>
/// <para>Object type must have a parameterless constructor.</para>
/// </summary>
/// <typeparam name="T">The type of object being written to the file.</typeparam>
/// <param name="filePath">The file path to write the object instance to.</param>
/// <param name="objectToWrite">The object instance to write to the file.</param>
/// <param name="append">If false the file will be overwritten if it already exists. If true the contents will be appended to the file.</param>
public static void WriteToXmlFile<T>(string filePath, T objectToWrite, bool append = false) where T : new()
{
TextWriter writer = null;
try
{
var serializer = new XmlSerializer(typeof(T));
writer = new StreamWriter(filePath, append);
serializer.Serialize(writer, objectToWrite);
}
finally
{
if (writer != null)
writer.Close();
}
}
/// <summary>
/// Reads an object instance from an XML file.
/// <para>Object type must have a parameterless constructor.</para>
/// </summary>
/// <typeparam name="T">The type of object to read from the file.</typeparam>
/// <param name="filePath">The file path to read the object instance from.</param>
/// <returns>Returns a new instance of the object read from the XML file.</returns>
public static T ReadFromXmlFile<T>(string filePath) where T : new()
{
TextReader reader = null;
try
{
var serializer = new XmlSerializer(typeof(T));
reader = new StreamReader(filePath);
return (T)serializer.Deserialize(reader);
}
finally
{
if (reader != null)
reader.Close();
}
}
Json
You must include a reference to Newtonsoft.Json assembly, which can be obtained from the Json.NET NuGet Package.
/// <summary>
/// Writes the given object instance to a Json file.
/// <para>Object type must have a parameterless constructor.</para>
/// <para>Only Public properties and variables will be written to the file. These can be any type though, even other classes.</para>
/// <para>If there are public properties/variables that you do not want written to the file, decorate them with the [JsonIgnore] attribute.</para>
/// </summary>
/// <typeparam name="T">The type of object being written to the file.</typeparam>
/// <param name="filePath">The file path to write the object instance to.</param>
/// <param name="objectToWrite">The object instance to write to the file.</param>
/// <param name="append">If false the file will be overwritten if it already exists. If true the contents will be appended to the file.</param>
public static void WriteToJsonFile<T>(string filePath, T objectToWrite, bool append = false) where T : new()
{
TextWriter writer = null;
try
{
var contentsToWriteToFile = JsonConvert.SerializeObject(objectToWrite);
writer = new StreamWriter(filePath, append);
writer.Write(contentsToWriteToFile);
}
finally
{
if (writer != null)
writer.Close();
}
}
/// <summary>
/// Reads an object instance from an Json file.
/// <para>Object type must have a parameterless constructor.</para>
/// </summary>
/// <typeparam name="T">The type of object to read from the file.</typeparam>
/// <param name="filePath">The file path to read the object instance from.</param>
/// <returns>Returns a new instance of the object read from the Json file.</returns>
public static T ReadFromJsonFile<T>(string filePath) where T : new()
{
TextReader reader = null;
try
{
reader = new StreamReader(filePath);
var fileContents = reader.ReadToEnd();
return JsonConvert.DeserializeObject<T>(fileContents);
}
finally
{
if (reader != null)
reader.Close();
}
}
Example
// Write the contents of the variable someClass to a file.
WriteToBinaryFile<SomeClass>("C:\someClass.txt", object1);
// Read the file contents back into a variable.
SomeClass object1= ReadFromBinaryFile<SomeClass>("C:\someClass.txt");
You can use the following:
/// <summary>
/// Serializes an object.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="serializableObject"></param>
/// <param name="fileName"></param>
public void SerializeObject<T>(T serializableObject, string fileName)
{
if (serializableObject == null) { return; }
try
{
XmlDocument xmlDocument = new XmlDocument();
XmlSerializer serializer = new XmlSerializer(serializableObject.GetType());
using (MemoryStream stream = new MemoryStream())
{
serializer.Serialize(stream, serializableObject);
stream.Position = 0;
xmlDocument.Load(stream);
xmlDocument.Save(fileName);
}
}
catch (Exception ex)
{
//Log exception here
}
}
/// <summary>
/// Deserializes an xml file into an object list
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="fileName"></param>
/// <returns></returns>
public T DeSerializeObject<T>(string fileName)
{
if (string.IsNullOrEmpty(fileName)) { return default(T); }
T objectOut = default(T);
try
{
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.Load(fileName);
string xmlString = xmlDocument.OuterXml;
using (StringReader read = new StringReader(xmlString))
{
Type outType = typeof(T);
XmlSerializer serializer = new XmlSerializer(outType);
using (XmlReader reader = new XmlTextReader(read))
{
objectOut = (T)serializer.Deserialize(reader);
}
}
}
catch (Exception ex)
{
//Log exception here
}
return objectOut;
}
You'll need to serialize to something: that is, pick binary, or xml (for default serializers) or write custom serialization code to serialize to some other text form.
Once you've picked that, your serialization will (normally) call a Stream that is writing to some kind of file.
So, with your code, if I were using XML Serialization:
var path = #"C:\Test\myserializationtest.xml";
using(FileStream fs = new FileStream(path, FileMode.Create))
{
XmlSerializer xSer = new XmlSerializer(typeof(SomeClass));
xSer.Serialize(fs, serializableObject);
}
Then, to deserialize:
using(FileStream fs = new FileStream(path, FileMode.Open)) //double check that...
{
XmlSerializer _xSer = new XmlSerializer(typeof(SomeClass));
var myObject = _xSer.Deserialize(fs);
}
NOTE: This code hasn't been compiled, let alone run- there may be some errors. Also, this assumes completely out-of-the-box serialization/deserialization. If you need custom behavior, you'll need to do additional work.
1. Restore Object From File
From Here you can deserialize an object from file in two way.
Solution-1: Read file into a string and deserialize JSON to a type
string json = File.ReadAllText(#"c:\myObj.json");
MyObject myObj = JsonConvert.DeserializeObject<MyObject>(json);
Solution-2: Deserialize JSON directly from a file
using (StreamReader file = File.OpenText(#"c:\myObj.json"))
{
JsonSerializer serializer = new JsonSerializer();
MyObject myObj2 = (MyObject)serializer.Deserialize(file, typeof(MyObject));
}
2. Save Object To File
from here you can serialize an object to file in two way.
Solution-1: Serialize JSON to a string and then write string to a file
string json = JsonConvert.SerializeObject(myObj);
File.WriteAllText(#"c:\myObj.json", json);
Solution-2: Serialize JSON directly to a file
using (StreamWriter file = File.CreateText(#"c:\myObj.json"))
{
JsonSerializer serializer = new JsonSerializer();
serializer.Serialize(file, myObj);
}
3. Extra
You can download Newtonsoft.Json from NuGet by following command
Install-Package Newtonsoft.Json
You can use JsonConvert from Newtonsoft library.
To serialize an object and write to a file in json format:
File.WriteAllText(filePath, JsonConvert.SerializeObject(obj));
And to deserialize it back into object:
var obj = JsonConvert.DeserializeObject<ObjType>(File.ReadAllText(filePath));
**1. Convert the json string to base64string and Write or append it to binary file.
2. Read base64string from binary file and deserialize using BsonReader.
**
public static class BinaryJson
{
public static string SerializeToBase64String(this object obj)
{
JsonSerializer jsonSerializer = new JsonSerializer();
MemoryStream objBsonMemoryStream = new MemoryStream();
using (BsonWriter bsonWriterObject = new BsonWriter(objBsonMemoryStream))
{
jsonSerializer.Serialize(bsonWriterObject, obj);
return Convert.ToBase64String(objBsonMemoryStream.ToArray());
}
//return Encoding.ASCII.GetString(objBsonMemoryStream.ToArray());
}
public static T DeserializeToObject<T>(this string base64String)
{
byte[] data = Convert.FromBase64String(base64String);
MemoryStream ms = new MemoryStream(data);
using (BsonReader reader = new BsonReader(ms))
{
JsonSerializer serializer = new JsonSerializer();
return serializer.Deserialize<T>(reader);
}
}
}
I am creating a dynamic form where if I click on "Add", a new panel appears with a set of buttons.
In this panel, I would like to add a list which will remember how many buttons were created. Thus I thought realize a list, but I want to increment again even though that we restart the console.
May be there is a tip to put it in a XMLfile. In this way my strategy can be renamed with the max of what is present in the CSV, but I do not know how to record and how to increment...
Any idea?
public class SerialStrategyFuture
{
public string StrategyName { get; set; }
public string NumStrategy { get; set; }
}
public void CreateStrategyFuture()
{
ConsoleStrategyItem strategyItemFuture = new ConsoleStrategyItem();
strategyItemFuture.Location = new Point(3, 3);
futureContainer.Height += 85;
futureContainer.Controls.Add(strategyItemFuture);
SerialStrategyFuture strategyFuture = new SerialStrategyFuture();
strategyFuture.StrategyName = "Strat Future ";
strategyFuture.NumStrategy = "How to increment it ???";
XmlSerializer serializer = new XmlSerializer(typeof(SerialStrategyFuture));
TextWriter textWriter = new StreamWriter(#"C:\Users\...");
serializer.Serialize(textWriter,strategyFuture);
textWriter.Close();
ConsoleStrategyItem.Instance.txtStrategyName.Text = "Strat Future 1 ";
}
I am not sure if you can serialize the utureContainer.Controls List. Threfore, I would use this way:
Declare a List ouf your buttons:
List controlList = new List();
each time your users creates a new button:
controlList.add(strategyItemFuture);
Serialize the List when your program closes or another opportune moment:
Deserialize it when your program starts.
build a foreach loop which pulls the buttons from the deserialized List.
Here are the two methods I use to serialize / deserialize
/// <summary>
/// Serializes a file to a compressed XML file. If an error occurs, the exception is NOT caught.
/// </summary>
/// <typeparam name="T">The Type</typeparam>
/// <param name="obj">The object.</param>
/// <param name="fileName">Name of the file.</param>
public static void SerializeToXML<T>(T obj, string fileName)
{
try
{
XmlSerializer serializer = new XmlSerializer(typeof(T));
using (FileStream fs = new FileStream(fileName, FileMode.Create))
{
using (GZipStream compressor = new GZipStream(fs, CompressionMode.Compress))
{
serializer.Serialize(compressor, obj);
}
}
}
catch (Exception)
{
throw;
}
}
/// <summary>
/// Deserializes an object from XML.
/// </summary>
/// <typeparam name="T">The object</typeparam>
/// <param name="file">The file.</param>
/// <returns>
/// The deserialized object
/// </returns>
public static T DeserializeFromXml<T>(string file)
{
T result;
XmlSerializer ser = new XmlSerializer(typeof(T));
using (FileStream fs = new FileStream(file, FileMode.Open))
{
using (GZipStream decompressor = new GZipStream(fs, CompressionMode.Decompress))
{
result = (T)ser.Deserialize(decompressor);
return result;
}
}
}
}
Usage:
SerializeToXML(controlList , yourPath);
this.controlList = DeserializeFromXml<List<ConsoleStrategyItem>>(yourPath);
I am doing a little bit more than just storing the number of buttons, but this has the advantage that you can store more data when your buttons have more logic.
I have an object exposed through a web service that is consumed by another system. That system also uses that same WSDL to return back an object on demand to us. I was wondering if it was possible to take that same object and relay it back to a the original object?
I tried to do the following and it wouldn't actually cast it back with the object populated... Any help would be great!
Thank you!
Note The method code listed below was based off of http://www.dotnetjohn.com/articles.aspx?articleid=173
public void ConvertBack()
{
ThirdParty.Animal animal;
using (var svc = new ThirdPartySoapClient())
thirdPartyAnimal = svc.GetAnimal("Identifier");
var xml = SerializeObject(thirdPartyAnimal, typeof(ThirdParty.Animal));
var originalAnimal = (OriginalNamespace.Animal)DeserializeObject(xml, typeof(OrginalNamespace.Animal));
Assert.AreEqual(originalAnimal.Name, animal.Name);
}
/// <summary>
/// Method to convert a custom Object to XML string
/// </summary>
/// <param name="pObject">Object that is to be serialized to XML</param>
/// <param name="typeOfObject">typeof() object that is being passed to be serialized to XML</param>
/// <returns>XML string</returns>
public string SerializeObject(object pObject, Type typeOfObject)
{
try
{
var memoryStream = new MemoryStream();
var xs = new XmlSerializer(typeOfObject);
var xmlTextWriter = new XmlTextWriter(memoryStream, Encoding.UTF8);
xs.Serialize(xmlTextWriter, pObject);
memoryStream = (MemoryStream) xmlTextWriter.BaseStream;
var xmlizedString = UTF8ByteArrayToString(memoryStream.ToArray());
return xmlizedString;
}
catch (Exception e)
{
Console.WriteLine(e);
return null;
}
}
/// <summary>
/// Method to reconstruct an Object from XML string
/// </summary>
/// <param name="pXmlizedString">XML To Be Converted to an Object</param>
/// <param name="typeOfObject">typeof() object that is being passed to be serialized to XML</param>
/// <returns></returns>
public object DeserializeObject(string pXmlizedString, Type typeOfObject)
{
var xs = new XmlSerializer(typeOfObject);
var memoryStream = new MemoryStream(StringToUTF8ByteArray(pXmlizedString));
new XmlTextWriter(memoryStream, Encoding.UTF8);
return xs.Deserialize(memoryStream);
}
/// <summary>
/// To convert a Byte Array of Unicode values (UTF-8 encoded) to a complete String.
/// </summary>
/// <param name="characters">Unicode Byte Array to be converted to String</param>
/// <returns>String converted from Unicode Byte Array</returns>
private static string UTF8ByteArrayToString(Byte[] characters)
{
var encoding = new UTF8Encoding();
var constructedString = encoding.GetString(characters);
return (constructedString);
}
/// <summary>
/// Converts the String to UTF8 Byte array and is used in De serialization
/// </summary>
/// <param name="pXmlString"></param>
/// <returns></returns>
private static Byte[] StringToUTF8ByteArray(string pXmlString)
{
var encoding = new UTF8Encoding();
var byteArray = encoding.GetBytes(pXmlString);
return byteArray;
}
When generating the proxy from WSDL there is an option called "/sharetypes" which should solve this problem
You can use it from the command line tools or in the options area of the "Add Web Service" dialogs