- В версии 2.x эти атрибуты работали должным образом.
- Я пробовал явно назначить обратные вызовы для MetaType в пользовательской модели RuntimeTypeModel, но это не работает с 3.2.26, хотя это работало с 2.x.
- Код назначения обратного вызова, используемый мной и программой воспроизведения, указан в конце этой темы.
- Есть ли в protobuf-net v3.x критическое изменение, которое влияет на вызов обратного вызова?
- Как правильно настроить обратные вызовы в версии 3.2.26, особенно при использовании пользовательских сопоставлений наследования с RuntimeTypeModel?
public static class ProtoSerializationHelper
{
private static RuntimeTypeModel Model;
public static byte[] Serialize(T instance)
{
using var ms = new MemoryStream();
CustomSerializer.Serialize(ms, instance);
return ms.ToArray();
}
public static T Deserialize(byte[] payload)
{
using var ms = new MemoryStream(payload);
var obj = (T)CustomSerializer.Deserialize(ms, null, typeof(T));
return obj;
}
public static RuntimeTypeModel CustomSerializer
{
get
{
if (Model == null)
{
Model = RuntimeTypeModel.Create();
//I have also tried using `false` as the value for `applyDefaultBehavior` flag with Model.Add API, doesn't seems have any effect.
var iAnimal = Model.Add(typeof(IAnimal), false);
var animal = Model.Add(typeof(Animal), true);
var dog = Model.Add(typeof(Dog), true);
iAnimal.AddSubType(100, typeof(Animal));
animal.AddSubType(101, typeof(Dog));
animal.SetCallbacks(beforeSerialize: nameof(Animal.OnSerializingCallback), afterSerialize: null, beforeDeserialize: null, afterDeserialize: nameof(Animal.OnDeserializingCallback));
dog.SetCallbacks(beforeSerialize: nameof(Dog.OnSerializingCallback), afterSerialize: null, beforeDeserialize: null, afterDeserialize: nameof(Dog.OnDeserializingCallback));
}
return Model;
}
}
}
Ниже приведены классы, которые я пытаюсь (де)сериализовать.
public interface IAnimal
{
int Id { get; set; }
string Name { get; set; }
DateTime CreatedUtc { get; set; }
}
[ProtoContract]
public class Animal : IAnimal
{
[ProtoMember(1)]
public int Id { get; set; }
[ProtoMember(2)]
public string Name { get; set; } = string.Empty;
[ProtoMember(3)]
public DateTime CreatedUtc { get; set; } = DateTime.UtcNow;
internal void OnDeserializingCallback()
{
Console.WriteLine($"[Animal:OnDeserializing Callback] Id={Id}, Name={Name}");
}
internal void OnSerializingCallback()
{
Console.WriteLine($"[Animal:OnSerializing Callback] Id={Id}, Name={Name}");
}
}
[ProtoContract]
public class Dog : Animal
{
[ProtoMember(1)]
public string Breed { get; set; } = string.Empty;
[ProtoMember(2)]
public int BarkVolume { get; set; }
internal void OnDeserializingCallback()
{
Console.WriteLine($"[Dog:OnDeserializing Callback] Id={Id}, Name={Name}");
}
internal void OnSerializingCallback()
{
Console.WriteLine($"[Dog:OnSerializing Callback] Id={Id}, Name={Name}");
}
}
Ниже приведен мой код, выполняющий (де)сериализацию.
var dog = new Dog
{
Id = 1,
Name = "Rex",
Breed = "Labrador",
BarkVolume = 7
};
var data = ProtoSerializationHelper.Serialize(dog);
var clone = ProtoSerializationHelper.Deserialize(data);
if (clone is Dog deserializedDog)
{
Console.WriteLine($"Dog details -> Id={deserializedDog.Id}, Name={deserializedDog.Name}, Breed={deserializedDog.Breed}, BarkVolume={deserializedDog.BarkVolume}");
}
Подробнее здесь: https://stackoverflow.com/questions/797 ... on-donot-w
Мобильная версия