Условное слияние в протобуф-сетиC#

Место общения программистов C#
Ответить
Anonymous
 Условное слияние в протобуф-сети

Сообщение Anonymous »

У меня есть некоторые очень конкретные требования для сериализации C# библиотеки: мне нужно, чтобы она была в состоянии обрабатывать круговые ссылки или несколько ссылок на один и тот же объект, быть способным к депутации в существующий объект и быть достаточно быстрым.

Protobuf-Net (2.4.6, Asreference Serialization была удалена позже, когда я не вписывается в критерий, но я не буду в номере:

Эта сериализация, конечно, снова запустит суррогат, который он обнаруживает, и на этот раз просто создает суррогат с необработанным объектом. Таким образом, конечная структура выглядит примерно так:


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
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»