У меня есть некоторые очень конкретные требования для сериализации C# Библиотеки: мне нужно, чтобы она была в состоянии обрабатывать круговые ссылки или несколько ссылок на один и тот же объект, быть способным дезиализировать в существующий объект и быть достаточно быстрым. Я хочу использовать его на узлах Godot (Game Engine), что означает, что существуют значительные накладные расходы для простого создания этих объектов. объект или объединен в существующий. /> Эта сериализация, конечно, снова запустит суррогат, который он обнаруживает, и на этот раз просто создает суррогат с необработанным объектом. Таким образом, конечная структура выглядит примерно так:
IdentifiabliableRrogate
- id
- directData: null
- serializeddata
- идентификация идентификатора (Br />
- nulableurragate (когда Deserialialial)
- идентификация: nulifiablabrogate (когда Deserialial)
- nulifiablabrogate (когда Deserialial)
- nulifiablabrogate. DirectData: фактический экземпляр t
- serializeddata: null < /em> < /p>
Однако я получаю исключение при десериализации сериализованности (внутренний суррогат): < /p>
'IdentifibleArrogate`1 [testidifiefiefie]' type 'testidentifiefite'. < /P>
< /blockquote>
Это исключение не возникает при вызове слияния вместо Deserialize. < /P>
. Я где -то читал, что неявные актеры теряются во время выполнения, что может иметь какое -то отношение к моей проблеме. Как исправления, так и предложения для библиотек, которые поддерживают все мои потребности, приветствуются! < /P>
Минимальный воспроизводимый пример:
< /p>
using System;
using System.Collections.Generic;
using System.IO;
using ProtoBuf;
public class Test {
public static void Main() {
IdentifiableSurrogate.printDebugMessages = true;
Console.WriteLine("---START---");
TestIdentifiable before = new TestIdentifiable(5);
Console.WriteLine("---SERIALIZING---");
using MemoryStream serializeStream = new MemoryStream();
Serializer.Serialize(serializeStream, before);
byte[] bytes = serializeStream.ToArray();
Console.WriteLine("---DESERIALIZING---");
// Without the following line, no exception occurs
IIdentifiable.UnregisterInstance(before); // to simulate server-client behavior where the object would not yet exist on the receiving end
using MemoryStream deserializeStream = new MemoryStream(bytes);
TestIdentifiable after = Serializer.Deserialize(deserializeStream);
Console.WriteLine("---END---");
Console.WriteLine("Before: " + before);
Console.WriteLine("After: " + after);
Console.WriteLine("Same Object? " + (before == after));
}
}
public interface IIdentifiable {
private static Dictionary instances = new Dictionary();
public static IIdentifiable? TryGetInstance(string id) {
return instances.GetValueOrDefault(id);
}
public static void RegisterInstance(IIdentifiable instance) {
if (string.IsNullOrEmpty(instance.Id)) {
instance.Id = Guid.NewGuid().ToString();
}
if (!instances.TryAdd(instance.Id, instance)) throw new Exception("Identifiable instance already exists");
}
public static void UnregisterInstance(IIdentifiable instance) {
instances.Remove(instance.Id);
}
public string Id { get; set; }
}
[ProtoContract]
public class IdentifiableSurrogate where T : class, IIdentifiable, new() {
public static bool printDebugMessages = false;
[ProtoMember(1)] public string? id;
[ProtoMember(2)] public byte[]? serializedData;
[ProtoMember(3)] public T? directData;
[ThreadStatic] private static bool suppressSurrogate;
public static implicit operator T?(IdentifiableSurrogate surrogate) {
try {
if (surrogate == null) return null;
if (surrogate.directData != null) {
if (printDebugMessages) Console.WriteLine("Resolving direct sub-surrogate for " + typeof(T).FullName + " with ID: " + surrogate.directData.Id);
return surrogate.directData;
}
if (surrogate.id == null || surrogate.serializedData == null) throw new ArgumentException("NodeSurrogate must have either DirectData or both NodePath and SerializedData set.");
IIdentifiable existingIdentifiable = IIdentifiable.TryGetInstance(surrogate.id);
// If the identifiable does not exist, create a new one
using MemoryStream ms = new MemoryStream(surrogate.serializedData);
if (existingIdentifiable == null) {
if (printDebugMessages) Console.WriteLine("Creating new instance of " + typeof(T).FullName + " with ID: " + surrogate.id);
// this also does not work
// IdentifiableSurrogate innerSurrogate = Serializer.Deserialize(ms);
// return innerSurrogate;
return Serializer.Deserialize(ms);
}
if (existingIdentifiable is not T existing) {
throw new ArgumentException("Path mismatch: Identifiable with ID " + surrogate.id + " already exists as a different type: " + existingIdentifiable.GetType().FullName + " instead of " + typeof(T).FullName);
}
// Merge data into existing instance
if (printDebugMessages) Console.WriteLine("Merging data into existing instance of " + typeof(T).FullName + " with ID: " + existing.Id);
Serializer.Merge(ms, existing);
return existing;
} catch (Exception e) {
Console.WriteLine("Error deserializing IdentifiableSurrogate:\n" + e.GetType() + " " + e.Message);
Console.WriteLine(e.StackTrace);
return null;
}
}
public static implicit operator IdentifiableSurrogate(T obj) {
if (obj == null) return null;
if (obj.Id == null) throw new ArgumentException("Cannot serialize Identifiable without an ID.");
if (suppressSurrogate) { // second pass, we only want to pass the object directly here (prevents infinite recursion)
if (printDebugMessages) Console.WriteLine("Creating direct sub-surrogate for " + obj.GetType().FullName + " with ID: " + obj.Id);
suppressSurrogate = false; // reset the flag for the next object
return new IdentifiableSurrogate {
directData = obj
};
}
// on first pass, we serialize the object to a byte array to prevent it from automatically being deserialized without checking the node path first (and potentially merging instead)
if (printDebugMessages) Console.WriteLine("Creating surrogate for " + obj.GetType().FullName + " with ID: " + obj.Id);
suppressSurrogate = true;
using MemoryStream ms = new MemoryStream();
Serializer.Serialize(ms, obj);
return new IdentifiableSurrogate {
id = obj.Id,
serializedData = ms.ToArray()
};
}
}
[ProtoContract(AsReferenceDefault = true, Surrogate = typeof(IdentifiableSurrogate))]
public class TestIdentifiable : IIdentifiable {
public string Id { get; set; }
[ProtoMember(1)] public int Value { get; set; }
public TestIdentifiable() { }
public TestIdentifiable(int value) {
IIdentifiable.RegisterInstance(this);
Value = value;
}
}
Подробнее здесь: https://stackoverflow.com/questions/797 ... otobuf-net
Условное слияние в протобуф-сети ⇐ C#
Место общения программистов C#
1753143317
Anonymous
У меня есть некоторые очень конкретные требования для сериализации C# Библиотеки: мне нужно, чтобы она была в состоянии обрабатывать круговые ссылки или несколько ссылок на один и тот же объект, быть способным дезиализировать в существующий объект и быть достаточно быстрым. Я хочу использовать его на узлах Godot (Game Engine), что означает, что существуют значительные накладные расходы для простого создания этих объектов. объект или объединен в существующий. /> Эта сериализация, конечно, снова запустит суррогат, который он обнаруживает, и на этот раз просто создает суррогат с необработанным объектом. Таким образом, конечная структура выглядит примерно так:
IdentifiabliableRrogate
- id
- directData: null
- serializeddata
- идентификация идентификатора (Br />
- nulableurragate (когда Deserialialial)
- идентификация: nulifiablabrogate (когда Deserialial)
- nulifiablabrogate (когда Deserialial)
- nulifiablabrogate. DirectData: фактический экземпляр t
- serializeddata: null < /em> < /p>
Однако я получаю исключение при десериализации сериализованности (внутренний суррогат): < /p>
'IdentifibleArrogate`1 [testidifiefiefie]' type 'testidentifiefite'. < /P>
< /blockquote>
Это исключение не возникает при вызове слияния вместо Deserialize. < /P>
. Я где -то читал, что неявные актеры теряются во время выполнения, что может иметь какое -то отношение к моей проблеме. Как исправления, так и предложения для библиотек, которые поддерживают все мои потребности, приветствуются! < /P>
Минимальный воспроизводимый пример:
< /p>
using System;
using System.Collections.Generic;
using System.IO;
using ProtoBuf;
public class Test {
public static void Main() {
IdentifiableSurrogate.printDebugMessages = true;
Console.WriteLine("---START---");
TestIdentifiable before = new TestIdentifiable(5);
Console.WriteLine("---SERIALIZING---");
using MemoryStream serializeStream = new MemoryStream();
Serializer.Serialize(serializeStream, before);
byte[] bytes = serializeStream.ToArray();
Console.WriteLine("---DESERIALIZING---");
// Without the following line, no exception occurs
IIdentifiable.UnregisterInstance(before); // to simulate server-client behavior where the object would not yet exist on the receiving end
using MemoryStream deserializeStream = new MemoryStream(bytes);
TestIdentifiable after = Serializer.Deserialize(deserializeStream);
Console.WriteLine("---END---");
Console.WriteLine("Before: " + before);
Console.WriteLine("After: " + after);
Console.WriteLine("Same Object? " + (before == after));
}
}
public interface IIdentifiable {
private static Dictionary instances = new Dictionary();
public static IIdentifiable? TryGetInstance(string id) {
return instances.GetValueOrDefault(id);
}
public static void RegisterInstance(IIdentifiable instance) {
if (string.IsNullOrEmpty(instance.Id)) {
instance.Id = Guid.NewGuid().ToString();
}
if (!instances.TryAdd(instance.Id, instance)) throw new Exception("Identifiable instance already exists");
}
public static void UnregisterInstance(IIdentifiable instance) {
instances.Remove(instance.Id);
}
public string Id { get; set; }
}
[ProtoContract]
public class IdentifiableSurrogate where T : class, IIdentifiable, new() {
public static bool printDebugMessages = false;
[ProtoMember(1)] public string? id;
[ProtoMember(2)] public byte[]? serializedData;
[ProtoMember(3)] public T? directData;
[ThreadStatic] private static bool suppressSurrogate;
public static implicit operator T?(IdentifiableSurrogate surrogate) {
try {
if (surrogate == null) return null;
if (surrogate.directData != null) {
if (printDebugMessages) Console.WriteLine("Resolving direct sub-surrogate for " + typeof(T).FullName + " with ID: " + surrogate.directData.Id);
return surrogate.directData;
}
if (surrogate.id == null || surrogate.serializedData == null) throw new ArgumentException("NodeSurrogate must have either DirectData or both NodePath and SerializedData set.");
IIdentifiable existingIdentifiable = IIdentifiable.TryGetInstance(surrogate.id);
// If the identifiable does not exist, create a new one
using MemoryStream ms = new MemoryStream(surrogate.serializedData);
if (existingIdentifiable == null) {
if (printDebugMessages) Console.WriteLine("Creating new instance of " + typeof(T).FullName + " with ID: " + surrogate.id);
// this also does not work
// IdentifiableSurrogate innerSurrogate = Serializer.Deserialize(ms);
// return innerSurrogate;
return Serializer.Deserialize(ms);
}
if (existingIdentifiable is not T existing) {
throw new ArgumentException("Path mismatch: Identifiable with ID " + surrogate.id + " already exists as a different type: " + existingIdentifiable.GetType().FullName + " instead of " + typeof(T).FullName);
}
// Merge data into existing instance
if (printDebugMessages) Console.WriteLine("Merging data into existing instance of " + typeof(T).FullName + " with ID: " + existing.Id);
Serializer.Merge(ms, existing);
return existing;
} catch (Exception e) {
Console.WriteLine("Error deserializing IdentifiableSurrogate:\n" + e.GetType() + " " + e.Message);
Console.WriteLine(e.StackTrace);
return null;
}
}
public static implicit operator IdentifiableSurrogate(T obj) {
if (obj == null) return null;
if (obj.Id == null) throw new ArgumentException("Cannot serialize Identifiable without an ID.");
if (suppressSurrogate) { // second pass, we only want to pass the object directly here (prevents infinite recursion)
if (printDebugMessages) Console.WriteLine("Creating direct sub-surrogate for " + obj.GetType().FullName + " with ID: " + obj.Id);
suppressSurrogate = false; // reset the flag for the next object
return new IdentifiableSurrogate {
directData = obj
};
}
// on first pass, we serialize the object to a byte array to prevent it from automatically being deserialized without checking the node path first (and potentially merging instead)
if (printDebugMessages) Console.WriteLine("Creating surrogate for " + obj.GetType().FullName + " with ID: " + obj.Id);
suppressSurrogate = true;
using MemoryStream ms = new MemoryStream();
Serializer.Serialize(ms, obj);
return new IdentifiableSurrogate {
id = obj.Id,
serializedData = ms.ToArray()
};
}
}
[ProtoContract(AsReferenceDefault = true, Surrogate = typeof(IdentifiableSurrogate))]
public class TestIdentifiable : IIdentifiable {
public string Id { get; set; }
[ProtoMember(1)] public int Value { get; set; }
public TestIdentifiable() { }
public TestIdentifiable(int value) {
IIdentifiable.RegisterInstance(this);
Value = value;
}
}
Подробнее здесь: [url]https://stackoverflow.com/questions/79705563/conditional-merge-in-protobuf-net[/url]
Ответить
1 сообщение
• Страница 1 из 1
Перейти
- Кемерово-IT
- ↳ Javascript
- ↳ C#
- ↳ JAVA
- ↳ Elasticsearch aggregation
- ↳ Python
- ↳ Php
- ↳ Android
- ↳ Html
- ↳ Jquery
- ↳ C++
- ↳ IOS
- ↳ CSS
- ↳ Excel
- ↳ Linux
- ↳ Apache
- ↳ MySql
- Детский мир
- Для души
- ↳ Музыкальные инструменты даром
- ↳ Печатная продукция даром
- Внешняя красота и здоровье
- ↳ Одежда и обувь для взрослых даром
- ↳ Товары для здоровья
- ↳ Физкультура и спорт
- Техника - даром!
- ↳ Автомобилистам
- ↳ Компьютерная техника
- ↳ Плиты: газовые и электрические
- ↳ Холодильники
- ↳ Стиральные машины
- ↳ Телевизоры
- ↳ Телефоны, смартфоны, плашеты
- ↳ Швейные машинки
- ↳ Прочая электроника и техника
- ↳ Фототехника
- Ремонт и интерьер
- ↳ Стройматериалы, инструмент
- ↳ Мебель и предметы интерьера даром
- ↳ Cантехника
- Другие темы
- ↳ Разное даром
- ↳ Давай меняться!
- ↳ Отдам\возьму за копеечку
- ↳ Работа и подработка в Кемерове
- ↳ Давай с тобой поговорим...
Мобильная версия