Ignore a class property with marshalling - c#

I need to export an ObservableCollection of this class to a binary file:
[StructLayout(LayoutKind.Sequential)]
[XmlRoot("RxFrame")]
public class RxFrame : BaseClass
{
[XmlAttribute]
public string ID { get; set; } = "00000000";
[XmlAttribute]
public int IntVal{ get; set; } = 0;
[XmlAttribute]
public bool IsExtended { get; set; } = false;
public RxFrame()
{
}
}
and this is the function to export the data to binary:
[StructLayout(LayoutKind.Sequential)]
public class BaseClass
{
public BaseClass()
{ }
public virtual byte[] getBinaryData()
{
int size = Marshal.SizeOf(this);
IntPtr ptr = Marshal.AllocHGlobal(size);
byte[] buffer = new byte[Marshal.SizeOf(this)];
Marshal.StructureToPtr(this, ptr, false);
Marshal.Copy(ptr, buffer, 0, Marshal.SizeOf(this));
Marshal.FreeHGlobal(ptr);
return buffer;
}
}
And this is the loop over each element:
using (FileStream mstream = File.Open(filePathParam + "RX.bin", FileMode.Create))
{
BinaryWriter bWriter = new BinaryWriter(mstream, Encoding.UTF8);
bWriter.Write(ListeRxFrames.Count);
foreach (RxFrame rx in ListeRxFrames)
{
bWriter.Write(rx.getBinaryData());
}
bWriter.Close();
}
This is working fine, but I only need to export the IntVal and IsExtended properties of the RxFrame class to binary. How do I do this?

There's no way to ignore a field when marshaling the object. Maybe you need to create a separate class for the data you want to marshal.

Related

How to export a class in a binary file

I need to export into a binary file an observable collection. This file will be parsed by an embeded software.
This is my class of Led configuration :
[XmlRoot("ConfLed")]
public class LedVals
{
#region Properties
[XmlAttribute]
public int ID { get; set; }
[XmlAttribute]
public string Type { get; set; } = "Trigger";
[XmlAttribute]
public string Binding { get; set; } = "OFF";
[XmlAttribute]
public int Trigger1 { get; set; } = 0;
[XmlAttribute]
public int Trigger2 { get; set; } = 0;
[XmlAttribute]
public string ColorT0 { get; set; } = "#000000";
[XmlAttribute]
public string ColorT1 { get; set; } = "#000000";
[XmlAttribute]
public string ColorT2 { get; set; } = "#000000";
#endregion
public LedVals()
{
}
public LedVals(int idParam, string typeParam, string bindingParam, int trig1Param, int trig2Param, string c0Param, string c1Param, string c2Param)
{
this.ID = idParam;
this.Type = typeParam;
this.Binding = bindingParam;
this.Trigger1 = trig1Param;
this.Trigger2 = trig2Param;
this.ColorT0 = c0Param;
this.ColorT1 = c1Param;
this.ColorT2 = c2Param;
}
}
And this is my serialize function for the observable collection of LedVals class (ListeLedTable) that I need to export:
public void SerializeLedTable(string filePathParam)
{
try
{
using (Stream mstream = File.Open(filePathParam + ".bin", FileMode.Create))
{
BinaryFormatter bin = new BinaryFormatter();
bin.Serialize(mstream, ListeLedTable);
}
}
}
The result is a file with binary values of the class properties and text description of the observable collection structure.
Is there a way to export properties values of a class like this ?
I can use a binaryWriter to write each property of my class in a loop, but I thought there might a simpler solution.
Thank you !
Use Marshal Techniques :
class Program
{
static void Main(string[] args)
{
LedVals ledVals = new LedVals();
int size = Marshal.SizeOf(ledVals); ;
IntPtr ptr = Marshal.AllocHGlobal(size);
byte[] buffer = new byte[Marshal.SizeOf(ledVals)];
Marshal.StructureToPtr(ledVals, ptr, true);
Marshal.Copy(ptr, buffer, 0, Marshal.SizeOf(ledVals));
Marshal.FreeHGlobal(ptr);
FileStream stream = File.OpenWrite("FILENAME");
BinaryWriter bWriter = new BinaryWriter(stream, Encoding.UTF8);
bWriter.Write(buffer);
}
}
[StructLayout(LayoutKind.Sequential)]
public class LedVals
{
public int ID { get; set; }
}
Using .NET binary serialization for any interop is a bad idea.
XML might be a better choice, but embedded devices usually lack the required horsepower to do any XML processing. I don't know what your embedded platform is, but there's a chance you could use Protocol Buffers (Protocol Buffers) to transfer binary data back and forth.

Serialize POCO to Simple Byte Array

I have a need to serialize the following type
public class MspMessage {
[DataMember(Order = 1), ProtoMember(1)]
public byte[] Prefix { get; private set; }
[DataMember(Order = 2), ProtoMember(2)]
public MspMessageType MessageType { get; private set; }
[DataMember(Order = 3), ProtoMember(3)]
public int DataLength { get; private set; }
[DataMember(Order = 4), ProtoMember(4)]
public MspCodes MspCode { get; private set; }
[DataMember(Order = 5), ProtoMember(5)]
public byte[] Data { get; private set; }
[DataMember(Order = 6), ProtoMember(6)]
public byte Checksum
{
get; private set;
}
public MspMessage(MspMessageType messageType, MspCodes mspCode, byte[] data) {
Prefix = new byte[] { 36, 77 };
MessageType = messageType;
MspCode = mspCode;
Data = data;
DataLength = data?.Length ?? 0;
if (data == null || data.Length == 0) {
Checksum = (byte)(0 ^ (int)MspCode);
} else {
var checksum = data.Length ^ (int)MspCode;
checksum = data.Aggregate(checksum, (current, t) => current ^ t);
Checksum = (byte)checksum;
}
}
}
Into a simple binary array like this: {36, 77, 60, 0, 1, 1}. I hacked around with BinaryFormatter and protobuf-net, but both produce added output besides the pure contents of the type. What is the most efficient way to go about this? It's my intention to create derived types that will have additional fields. Thanks!
I wound up writing my own IFormatter which essentially is the same thing as a ToByteArray() and FromByteArray(). Thanks!

Xamarin.Forms PCL SQLiteException: file is encrypted or is not a database and 'Resource' does not contain a definition for 'Raw'

Today I am facing with this issue: I got such a exception :
SQLite.SQLiteException: file is encrypted or is not a database
I am doing project regarding this guide: https://developer.xamarin.com/guides/xamarin-forms/working-with/databases/ .
This is my Database class where I am initialize Connection and Table creation:
public class ThingDatabase
{
SQLiteConnection database;
public ThingDatabase()
{
database = DependencyService.Get<ISQLite>().GetConnection();
database.CreateTable<ThingObj>();
}
}
Here is my object class:
public class ThingObj
{
public ThingObj()
{
}
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
public string City { get; set; }
public string ThingNumber { get; set; }
public bool IsStarted { get; set; }
}
And here is my created SQLite_Android class regarding example:
[assembly: Dependency(typeof(SQLite_Android))]
...
{
public class SQLite_Android : ISQLite
{
public SQLite_Android() { }
public SQLite.SQLiteConnection GetConnection() {
var sqliteFilename = "ThingSQLite.db3";
string documentsPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
var path = Path.Combine(documentsPath, sqliteFilename);
Console.WriteLine(path);
if (!File.Exists(path))
{
var s = Forms.Context.Resources.OpenRawResource(Resource.Raw.Database);
FileStream writeStream = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write);
ReadWriteStream(s, writeStream);
}
var conn = new SQLite.SQLiteConnection(path);
return conn;
}
void ReadWriteStream(Stream readStream, Stream writeStream)
{
int Length = 256;
Byte[] buffer = new Byte[Length];
int bytesRead = readStream.Read(buffer, 0, Length);
while (bytesRead > 0)
{
writeStream.Write(buffer, 0, bytesRead);
bytesRead = readStream.Read(buffer, 0, Length);
}
readStream.Close();
writeStream.Close();
}
}
When I am debugging, after database.CreateTable<ThingObj>(); breakpoint, I am getting that exception and redirected to SQLite.cs class last line.
EDIT : Regarding AkashAmin suggestion I changed sqliteFilename to another string name and solved previous issue. Now I want to create database file in path, but unfortunately Resource.Designer.cs file do not auto generate Raw partial class in Resource.designer.cs . I am getting this error:
'Resource' does not contain a definition for 'Raw'

Deserialisation unable to list data

I am trying to create an application that can both serialise and deserialise data, i can serialise the information however when i try to read the information i am left with an empty list and i do not know why.
My Serialization class
[Serializable()]
public class FileSerilizeObject
{
public static string FileName { get; set; }
public static string Extension { get; set; }
public static string Base64 { get; set; }
public FileSerilizeObject(string filename, string extension, string base64vaulue)
{
FileName = filename;
Extension = extension;
Base64 = base64vaulue;
}
}
}
My serialization/deserialization methods
public void Serialize(List<FileSerilizeObject> List)
{
using (Stream stream = File.Open(savepath, FileMode.OpenOrCreate))
{
BinaryFormatter bin = new BinaryFormatter();
bin.Serialize(stream, List);
stream.Close();
}
}
public List<FileSerilizeObject> Deserialised(string OpenPath)
{
List<FileSerilizeObject> defo;
using(Stream stream = File.Open(OpenPath, FileMode.Open))
{
BinaryFormatter bin = new BinaryFormatter();
defo = (List<FileSerilizeObject>)bin.Deserialize(stream);
}
return defo;
}
I have checked to insure that the file paths are correct and that the file itself is not empty.Everything is fine however the "defo" list is always empty so i can only assume the issue is with the defo = (List<FileSerilizeObject>)bin.Deserialize(stream);Line however i do not know why.
You need to remove the static from your properties
[Serializable]
public class FileSerializeObject
{
public string FileName { get; set; }
public string Extension { get; set; }
public string Base64 { get; set; }
public FileSerializeObject(string filename, string extension, string base64vaulue)
{
FileName = filename;
Extension = extension;
Base64 = base64vaulue;
}
}
Try to set the [Serializable()] attribute for each property.
So it would look like this:
[Serializable()]
public class FileSerilizeObject
{
[Serializable()]
public string FileName { get; set; }
[Serializable()]
public string Extension { get; set; }
[Serializable()]
public string Base64 { get; set; }
public FileSerilizeObject(string filename, string extension, string base64vaulue)
{
FileName = filename;
Extension = extension;
Base64 = base64vaulue;
}
}
}
EDIT: Removed static keyword from properties.
I tested your code into a console application and it is working for me, I tested with VS 2013 but I used the same code that you wrote above.
Some details:
1. I removed the word static form the "FileSerilizeObject"
The class FileSerilizeObject
[Serializable()]
public class FileSerilizeObject
{
public string FileName { get; set; }
public string Extension { get; set; }
public string Base64 { get; set; }
public FileSerilizeObject(string filename, string extension, string base64vaulue)
{
FileName = filename;
Extension = extension;
Base64 = base64vaulue;
}
}
Functions
public static void Serialize(List<FileSerilizeObject> List)
{
using (Stream stream = File.Open(#"C:\Users\ttest\Desktop\folder1\data.bin", FileMode.OpenOrCreate))
{
BinaryFormatter bin = new BinaryFormatter();
bin.Serialize(stream, List);
stream.Close();
}
}
public static List<FileSerilizeObject> Deserialised(string OpenPath)
{
List<FileSerilizeObject> defo;
using (Stream stream = File.Open(OpenPath, FileMode.Open))
{
BinaryFormatter bin = new BinaryFormatter();
defo = (List<FileSerilizeObject>)bin.Deserialize(stream);
}
return defo;
}
Main
var bytes = Encoding.UTF8.GetBytes("dffesdbcdef==");
var base64 = Convert.ToBase64String(bytes);
FileSerilizeObject f1 = new FileSerilizeObject("test", "jpg", base64);
bytes = Encoding.UTF8.GetBytes("ggasddbcdef==");
base64 = Convert.ToBase64String(bytes);
FileSerilizeObject f2 = new FileSerilizeObject("test2", "png", base64);
bytes = Encoding.UTF8.GetBytes("asddffasdasdasdesdbcdef==");
base64 = Convert.ToBase64String(bytes);
FileSerilizeObject f3 = new FileSerilizeObject("test3", "doc", base64);
List<FileSerilizeObject> lFiles = new List<FileSerilizeObject>();
lFiles.Add(f1);
lFiles.Add(f2);
lFiles.Add(f3);
Serialize(lFiles);
Deserialised(#"C:\Users\rjimen4x\Desktop\tutoriales\data.bin");

protobuf does not deserialize object corrctly

I have three classes:
[ProtoContract]
public class Message
{
[ProtoMember(1)]
public int MethodId { set; get; }
[ProtoMember(2)]
public CustomArgs Arguments { set; get; }
}
[ProtoContract]
public class CustomArgs
{
[ProtoMember(1)]
public int IntVal { set; get; }
[ProtoMember(2)]
public string StrVal { set; get; }
[ProtoMember(3)]
public CycleData Cd { set; get; }
}
[ProtoContract]
public class CycleData
{
[ProtoMember(1)]
public int Id { set; get; }
[ProtoMember(2, AsReference = true)]
public CycleData Owner { set; get; }}
So when I create objects then serialize and deserialize it the Arguments property stay null but orignal object have a value. The sample code is:
static void Main(string[] args)
{
CycleData cd = new CycleData()
{
Id = 5
};
cd.Owner = cd;
CustomArgs a = new CustomArgs()
{
IntVal = 5,
StrVal = "string",
Cd = cd
};
Message oldMsg = new Message()
{
MethodId = 3,
Arguments = a
};
Stream st = new MemoryStream();
ProtoBuf.Serializer.Serialize(st, oldMsg);
var newMsg = ProtoBuf.Serializer.Deserialize<Message>(st);
}
So newMsg.Arguments is null after deserialize. What i do wrong?
You have a simple error. Once you serialize/write to the memstream, the .Pointer remain at the end of the stream. Deserializing immediately after using on the same stream fails because there is nothing to read after that point. Just reset it:
using (Stream st = new MemoryStream())
{
ProtoBuf.Serializer.Serialize(st, oldMsg);
st.Position = 0; // point to start of stream
var newMsg = ProtoBuf.Serializer.Deserialize<Message>(st);
}
I also put the stream in a using block to dispose of it.

Categories

Resources