Здесь не так много объяснений, вот что у меня есть:
public struct PACKET_HEADER
{
public string computerIp;
public string computerName;
public string computerCustomName;
};
public struct PACKET
{
public PACKET_HEADER pktHdr;
public PACKET_DATA pktData;
};
public struct PACKET_DATA
{
public Command command;
public string data;
};
public struct DATA_MESSAGE
{
public string message;
};
public struct DATA_FILE
{
public string fileName;
public long fileSize;
};
В основном я хочу, чтобы поле данных в PACKET_DATA могло быть либо DATA_FILE, либо DATA_MESSAGE. Я знаю, что тип нужно изменить, но я не знаю, что делать, можно ли использовать дженерики?
конечный результат должен быть таким, чтобы я мог сделать либо:
pktData.data.fileName или pktData.data.message
РЕДАКТИРОВАТЬ
Я мог бы сделать:
public struct PACKET_DATA
{
public Command command;
public string data;
public DATA_MESSAGE data_message;
public DATA_FILE data_file;
};
и просто установить значение null для data_message или файла, когда они мне не понадобятся? как это повлияет на сериализацию / байтовый массив и отправляемые данные. Если бы я использовал классы, у меня не было бы такой же проблемы
РЕДАКТИРОВАТЬ 2
public struct PACKET_MESSAGE
{
public PACKET_HEADER pktHdr;
public Command command;
public DATA_MESSAGE pktData;
};
public struct PACKET_FILE
{
public PACKET_HEADER pktHdr;
public Command command;
public DATA_FILE pktData;
};
Редактировать 3
У меня есть стерилизатор и де-стерилизатор, который работает с моим исходным примером, если с этим нет проблем, то фактическая сериализация
РЕДАКТИРОВАТЬ 4
вроде бы все работает, за исключением одной вещи, которую мой сериализатор получает «Попытка чтения или записи в защищенную память. Это часто указывает на то, что другая память повреждена». gunna взгляните на него, когда опубликуете мое рабочее решение :)
РЕДАКТИРОВАТЬ 5
public static byte[] Serialize(object anything)
{
int rawsize = Marshal.SizeOf(anything);
byte[] rawdatas = new byte[rawsize];
GCHandle handle = GCHandle.Alloc(rawdatas, GCHandleType.Pinned);
IntPtr buffer = handle.AddrOfPinnedObject();
Marshal.StructureToPtr(anything, buffer, false);
handle.Free();
return rawdatas;
}
public static object Deserialize(byte[] rawdatas, Type anytype)
{
int rawsize = Marshal.SizeOf(anytype);
if (rawsize > rawdatas.Length)
return null;
GCHandle handle = GCHandle.Alloc(rawdatas, GCHandleType.Pinned);
IntPtr buffer = handle.AddrOfPinnedObject();
object retobj = Marshal.PtrToStructure(buffer, anytype);
handle.Free();
return retobj;
}
ОКОНЧАТЕЛЬНОЕ
Структуры:
public struct PACKET_HEADER
{
public string computerIp;
public string computerName;
public string computerCustomName;
};
public struct PACKET
{
public PACKET_HEADER pktHdr;
public PACKET_DATA pktData;
};
public struct PACKET_DATA
{
public Command command;
public IDATA data;
public T GetData<T>() where T : IDATA
{
return (T)(data);
}
}
public interface IDATA { }
public struct DATA_MESSAGE : IDATA
{
public string message;
}
public struct DATA_FILE : IDATA
{
public string fileName;
public long fileSize;
}
Как создать новый пакет (возможно, можно объединить вместе tbh):
public static PACKET CreatePacket(Command command)
{
PACKET packet;
packet.pktHdr.computerIp = Settings.ComputerIP;
packet.pktHdr.computerName = Settings.ComputerName;
packet.pktHdr.computerCustomName = Settings.ComputerCustomName;
packet.pktData.command = command;
packet.pktData.data = null;
return packet;
}
public static PACKET CreatePacket(Command command, DATA_MESSAGE data_message)
{
PACKET packet;
packet.pktHdr.computerIp = Settings.ComputerIP;
packet.pktHdr.computerName = Settings.ComputerName;
packet.pktHdr.computerCustomName = Settings.ComputerCustomName;
packet.pktData.command = command;
packet.pktData.data = data_message;
return packet;
}
public static PACKET CreatePacket(Command command, DATA_FILE data_file)
{
PACKET packet;
packet.pktHdr.computerIp = Settings.ComputerIP;
packet.pktHdr.computerName = Settings.ComputerName;
packet.pktHdr.computerCustomName = Settings.ComputerCustomName;
packet.pktData.command = command;
packet.pktData.data = data_file;
return packet;
}
(de ) сериализации выше.
публичный класс Garage {частный список Допустим, у меня есть настольное приложение, которое действует как гараж для группы автомобилей: В настольном приложении есть кнопка «моделирования», которая запускает новый поток и начинает звонить методы на Гараже, Машине, Колесе и т. д. Выполнение этой симуляции может занять до 10 минут. На данный момент у меня есть класс, который выглядит так: Этот код только «читает» и никогда не «пишет» Таким образом, приведенное выше может занять много времени в зависимости от того, насколько сильно автомобили нуждаются в обслуживании. Пока происходит вышеуказанное, пользователь может продолжать работать с настольным приложением. Они могут выбрать изменение цвета автомобиля, который используется в вышеуказанной транзакции. Мой вопрос заключается в том, предотвратит ли вышеуказанная длительная транзакция изменение цвета автомобиля? т.е. пользователь, изменяющий цвет автомобиля в настольном приложении, не сможет зафиксировать изменение, пока длинная транзакция не будет завершена? @Entity
public class Garage {
private List<Car> cars = new ArrayList<Car>();
...
}
beginTransaction();
Garage garage = garageDao.findGarage(1);
List<Car> cars = garage.getCars();
for (Car car : cars) {
// call methods on the car to lazily fetch other things like wheels...
}
commitTransaction();