2013-06-21 3 views
1

У меня есть приложение C#, которое считывает/записывает сообщения с определенного предопределенного протокола с/на USB. Поэтому у меня есть как минимум 2 варианта. Один - сериализовать/десериализовать. Другой - маршал. Сначала я выбирал первый вариант, и он работал нормально. Но после того, как все больше и больше типов сообщений введены, меня раздражает громоздкая реализация для каждого типа сообщения и чувствую, что маршал может быть лучшим способом. Раньше я не использовал маршала. Правильно ли это? Я сделал несколько тестов. Одна из проблем, с которой я сталкиваюсь, - это когда у меня есть структура с массивом, как писать на нее? Такие, как: -C# Marshalling vs Serialization

[StructLayout(LayoutKind.Sequential, Size=TotalBytesInStruct),Serializable] 
    public struct SomeData 
    { 
     /// char[15] 
     [MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 15)] 
     public sbyte[] data; 

     /// int[15] 
     [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 15)] 
     public int[] prob; 
    } 

Оказывается, что данные и пробы являются ссылками, и я должен новым объект, чтобы использовать их, что звучит не совсем правильно меня. Мне нужно, чтобы вся структура была непрерывным блоком памяти, и я не думаю, что новый оператор сделает это для меня.

Любое предложение действительно оценили

Ниже показано, как я сделал с помощью сериализации.

List<byte> rawData = new List<byte>(); 
    rawData.AddRange(BitConverter.GetBytes(ProtocolVersion)); 
    // 16 bytes for operator ID 
    byte[] temp = new byte[16]; 
    Array.Copy(Encoding.ASCII.GetBytes(OperatorId), temp, OperatorId.Length > temp.Length ? temp.Length : OperatorId.Length); 
    rawData.AddRange(temp); 

    // 16 bytes for operator password 
    Array.Clear(temp, 0, temp.Length); 
    Array.Copy(Encoding.ASCII.GetBytes(OperatorPassword), temp, OperatorPassword.Length > temp.Length ? temp.Length : OperatorPassword.Length); 
    rawData.AddRange(temp); 

Ниже, как я сделал на сортировочной

static byte[] RawSerialize<T>(T obj) 
    { 
     if (obj == null) 
     { 
      return null; 
     } 

     int size = Marshal.SizeOf(obj); 
     byte[] result = new byte[size]; 
     IntPtr buffer = Marshal.AllocHGlobal(size); 
     Marshal.StructureToPtr(obj, buffer, false); 
     Marshal.Copy(buffer, result, 0, size); 

     return result; 
    } 
+0

Существуют способы сериализации и десериализации в общем виде с очень маленькой церемонией. Можете ли вы показать нам, как вы это делаете? –

+0

Кроме того, если вы могли бы рассказать нам немного больше о том, почему сериализация не работает для вас, и почему вы думаете, что маршалинг может быть лучше, это было бы здорово. –

+0

У меня есть пример кода. Я не сказал, что это не работает. Просто потому, что мне приходится разбирать сообщения для разных типов. – leon

ответ

0

Кажется, что мне нужно только новый массив, как следующий, и он прекрасно работает.

[StructLayout(LayoutKind.Sequential, Pack = 1)] 
public class SomeData 
{ 
    /// char[15] 
    [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 15)] 
    public byte[] data = new byte[15]; 

    /// int[15] 
    [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 15)] 
    public int[] prob = new int[15]; 
}