Сообщество Vue обычно предпочитает использовать Vuex для решения этой проблемы. Изменения приводятся к состоянию Vuex, и представление DOM просто вытекает из этого, устраняя необходимость в событиях во многих случаях.
Запрет на то, что повторное излучение, вероятно, станет следующим лучшим выбором, а наконец вы можете использовать шину событий, подробно описанную в другом высокоприоритетном ответе на этот вопрос.
Ниже приведен мой первоначальный ответ на этот вопрос, и это не тот подход, который я бы принял сейчас , имея больше опыта с Vue.
Это случай, когда я могу не согласиться с выбором дизайна Vue и прибегать к DOM.
В grand-child
,
methods: {
doEvent() {
try {
this.$el.dispatchEvent(new Event("eventtriggered"));
} catch (e) {
// handle IE not supporting Event constructor
var evt = document.createEvent("Event");
evt.initEvent("eventtriggered", true, false);
this.$el.dispatchEvent(evt);
}
}
}
и в parent
,
mounted(){
this.$el.addEventListener("eventtriggered", () => this.performAction())
}
В противном случае вы должны переизлучить или использовать шину.
Примечание: я добавил код в методе doEvent для обработки IE; этот код можно извлечь многоразовым способом.
Это довольно просто, используя сортировку.
Верх файла
using System.Runtime.InteropServices
Функция
byte[] getBytes(CIFSPacket str) {
int size = Marshal.SizeOf(str);
byte[] arr = new byte[size];
IntPtr ptr = Marshal.AllocHGlobal(size);
Marshal.StructureToPtr(str, ptr, true);
Marshal.Copy(ptr, arr, 0, size);
Marshal.FreeHGlobal(ptr);
return arr;
}
И для ее возврата:
CIFSPacket fromBytes(byte[] arr) {
CIFSPacket str = new CIFSPacket();
int size = Marshal.SizeOf(str);
IntPtr ptr = Marshal.AllocHGlobal(size);
Marshal.Copy(arr, 0, ptr, size);
str = (CIFSPacket)Marshal.PtrToStructure(ptr, str.GetType());
Marshal.FreeHGlobal(ptr);
return str;
}
В вашей структуре вам нужно будет поставить это перед строкой
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)]
public string Buffer;
И убедитесь, что SizeConst имеет такую же большую возможную строку.
И вы должны, вероятно, прочитать это: http://msdn.microsoft.com/en-us/library/4ca6d5z7.aspx
Это можно сделать очень просто.
Определите свою структуру явно с помощью [StructLayout(LayoutKind.Explicit)]
int size = list.GetLength(0);
IntPtr addr = Marshal.AllocHGlobal(size * sizeof(DataStruct));
DataStruct *ptrBuffer = (DataStruct*)addr;
foreach (DataStruct ds in list)
{
*ptrBuffer = ds;
ptrBuffer += 1;
}
Этот код может быть написан только в небезопасном контексте. Вы должны освободить addr
, когда закончите с ним.
Marshal.FreeHGlobal(addr);
Я бы посмотрел на классы BinaryReader и BinaryWriter. Недавно мне пришлось сериализовать данные в массив байтов (и обратно) и только найти эти классы после того, как я сам их переписал сам.
http://msdn.microsoft.com/en- us / library / system.io.binarywriter.aspx
На этой странице также есть хороший пример.
Посмотрите на эти методы:
byte [] StructureToByteArray(object obj)
{
int len = Marshal.SizeOf(obj);
byte [] arr = new byte[len];
IntPtr ptr = Marshal.AllocHGlobal(len);
Marshal.StructureToPtr(obj, ptr, true);
Marshal.Copy(ptr, arr, 0, len);
Marshal.FreeHGlobal(ptr);
return arr;
}
void ByteArrayToStructure(byte [] bytearray, ref object obj)
{
int len = Marshal.SizeOf(obj);
IntPtr i = Marshal.AllocHGlobal(len);
Marshal.Copy(bytearray,0, i,len);
obj = Marshal.PtrToStructure(i, obj.GetType());
Marshal.FreeHGlobal(i);
}
Это бесстыдная копия другого потока, который я нашел в Googling!
Update: Для получения дополнительной информации проверьте источник
Я придумал другой подход, который мог бы преобразовать любой struct
без хлопот фиксирующей длины, однако полученный массив байтов имел бы немного больше накладных расходов.
Вот пример struct
:
[StructLayout(LayoutKind.Sequential)]
public class HelloWorld
{
public MyEnum enumvalue;
public string reqtimestamp;
public string resptimestamp;
public string message;
public byte[] rawresp;
}
Как вы можете видеть, для всех этих структур потребуется добавить атрибуты фиксированной длины. Который часто мог занять больше места, чем требовалось. Обратите внимание, что требуется LayoutKind.Sequential
, так как мы хотим, чтобы отражение всегда давало нам тот же порядок, когда тянул за FieldInfo
. Мое вдохновение - от TLV
Type-Length-Value. Давайте посмотрим на код:
public static byte[] StructToByteArray<T>(T obj)
{
using (MemoryStream ms = new MemoryStream())
{
FieldInfo[] infos = typeof(T).GetFields(BindingFlags.Public | BindingFlags.Instance);
foreach (FieldInfo info in infos)
{
BinaryFormatter bf = new BinaryFormatter();
using (MemoryStream inms = new MemoryStream()) {
bf.Serialize(inms, info.GetValue(obj));
byte[] ba = inms.ToArray();
// for length
ms.Write(BitConverter.GetBytes(ba.Length), 0, sizeof(int));
// for value
ms.Write(ba, 0, ba.Length);
}
}
return ms.ToArray();
}
}
Вышеупомянутая функция просто использует BinaryFormatter
для сериализации неизвестного размера raw object
, и я просто отслеживаю размер и сохраняю его внутри выхода MemoryStream
тоже.
public static void ByteArrayToStruct<T>(byte[] data, out T output)
{
output = (T) Activator.CreateInstance(typeof(T), null);
using (MemoryStream ms = new MemoryStream(data))
{
byte[] ba = null;
FieldInfo[] infos = typeof(T).GetFields(BindingFlags.Public | BindingFlags.Instance);
foreach (FieldInfo info in infos)
{
// for length
ba = new byte[sizeof(int)];
ms.Read(ba, 0, sizeof(int));
// for value
int sz = BitConverter.ToInt32(ba, 0);
ba = new byte[sz];
ms.Read(ba, 0, sz);
BinaryFormatter bf = new BinaryFormatter();
using (MemoryStream inms = new MemoryStream(ba))
{
info.SetValue(output, bf.Deserialize(inms));
}
}
}
}
Когда мы хотим преобразовать его обратно в исходное struct
, мы просто прочтем длину и вернем его обратно в BinaryFormatter
, который в свою очередь сбрасывает его обратно в struct
.
Эти 2 функции являются общими и должны работать с любым struct
, я протестировал вышеуказанный код в моем проекте C#
, где у меня есть сервер и клиент, подключенный и обменивающийся через NamedPipeStream
и я пересылаю свой struct
в виде массива байтов от одного и к другому и преобразовываю его обратно.
Я считаю, что мой подход может быть лучше, поскольку он не фиксирует длину самого struct
и единственные накладные расходы - это всего лишь int
для каждого поля, которое у вас есть в вашей структуре. Внутри байтового массива, генерируемого BinaryFormatter
, есть немного незначительных накладных расходов, но кроме этого, это немного.
@Abdel Olakara ответ donese не работает в .net 3.5, следует изменить следующим образом:
public static void ByteArrayToStructure<T>(byte[] bytearray, ref T obj)
{
int len = Marshal.SizeOf(obj);
IntPtr i = Marshal.AllocHGlobal(len);
Marshal.Copy(bytearray, 0, i, len);
obj = (T)Marshal.PtrToStructure(i, typeof(T));
Marshal.FreeHGlobal(i);
}
Если вы действительно хотите, чтобы он был FAST, вы можете сделать это, используя небезопасный код с CopyMemory. CopyMemory примерно в 5 раз быстрее (например, 800 МБ данных занимает 3 с для копирования через маршаллинг, а только для копирования с помощью CopyMemory .6s). Этот метод ограничивает использование только данных, которые фактически хранятся в самой структуре struct blob, например. числа или массивы байтов с фиксированной длиной.
[DllImport("kernel32.dll", EntryPoint = "CopyMemory", SetLastError = false)]
private static unsafe extern void CopyMemory(void *dest, void *src, int count);
private static unsafe byte[] Serialize(TestStruct[] index)
{
var buffer = new byte[Marshal.SizeOf(typeof(TestStruct)) * index.Length];
fixed (void* d = &buffer[0])
{
fixed (void* s = &index[0])
{
CopyMemory(d, s, buffer.Length);
}
}
return buffer;
}
В качестве основного ответа используется тип CIFSPacket, который не является (или больше не доступен) на C #, я написал правильные методы:
static byte[] getBytes(object str)
{
int size = Marshal.SizeOf(str);
byte[] arr = new byte[size];
IntPtr ptr = Marshal.AllocHGlobal(size);
Marshal.StructureToPtr(str, ptr, true);
Marshal.Copy(ptr, arr, 0, size);
Marshal.FreeHGlobal(ptr);
return arr;
}
static T fromBytes<T>(byte[] arr)
{
T str = default(T);
int size = Marshal.SizeOf(str);
IntPtr ptr = Marshal.AllocHGlobal(size);
Marshal.Copy(arr, 0, ptr, size);
str = (T)Marshal.PtrToStructure(ptr, str.GetType());
Marshal.FreeHGlobal(ptr);
return str;
}
Протестировано, они работают.
Header header = new Header();
Byte[] headerBytes = new Byte[Marshal.SizeOf(header)];
Marshal.Copy((IntPtr)(&header), headerBytes, 0, headerBytes.Length);
Это должно сделать трюк быстро, не так ли?
Похож на предопределенную структуру (C level) для некоторой внешней библиотеки. Маршал - ваш друг. Проверьте:
http://geekswithblogs.net/taylorrich/archive/2006/08/21/88665.aspx
для стартера, как бороться с этим. Обратите внимание, что вы можете - с атрибутами - определять такие вещи, как макет макета и обработка строк. На самом деле очень хороший подход.
Для этого не выполняются ни BinaryFormatter, ни MemoryStream.
Этот пример применим только к чистым типам blittable, например типам, которые могут быть memcpy'd непосредственно в C.
Пример - хорошо известная 64-битная структура
[StructLayout(LayoutKind.Sequential)]
public struct Voxel
{
public ushort m_id;
public byte m_red, m_green, m_blue, m_alpha, m_matid, m_custom;
}
Определено точно так же, структура будет автоматически упакована как 64-разрядная.
Теперь мы можем создать объем вокселей:
Voxel[,,] voxels = new Voxel[16,16,16];
И сохранить их все в байт array:
int size = voxels.Length * 8; // Well known size: 64 bits
byte[] saved = new byte[size];
GCHandle h = GCHandle.Alloc(voxels, GCHandleType.Pinned);
Marshal.Copy(h.AddrOfPinnedObject(), saved, 0, size);
h.Free();
// now feel free to save 'saved' to a File / memory stream.
Однако, поскольку OP хочет знать, как преобразовать структуру, наша структура Voxel может иметь следующий метод ToBytes
:
byte[] bytes = new byte[8]; // Well known size: 64 bits
GCHandle h = GCHandle.Alloc(this, GCHandleType.Pinned);
Marshal.Copy(hh.AddrOfPinnedObject(), bytes, 0, 8);
h.Free();
Marshal.StructureToPtr(str, ptr, false);
. Но нужно упомянуть, что я использую функции, завернутые в общий, хотя ... – Hi-Angel 10 October 2014 в 14:10