#java #c# #serialization #protocol-buffers #protobuf-net
Вопрос:
У меня есть 2 приложения, использующие protobuf между ними. Первый (C#) с использованием protobuf-сети с сериализуемыми настройками визуализации объектов:
[ProtoContract]
public class VisualSettings
{
[ProtoContract]
public class BodyPartHolder
{
[ProtoMember(1)]
public BodyPartType type;
[ProtoMember(2)]
public int id;
public BodyPartHolder() { }
public BodyPartHolder(BodyPartType type, int id)
{
this.type = type;
this.id = id;
}
public BodyPartHolder Copy()
{
return new BodyPartHolder(type, id);
}
}
public interface IPaintHolder
{
int id { get; set; }
}
public interface ICustomPaintHolder
{
HSBColor hsb { get; set; }
}
[ProtoContract]
[ProtoInclude(100, typeof(BaseBodyPaintHolder)), ProtoInclude(200, typeof(BaseWheelPaintHolder)), ProtoInclude(300, typeof(BaseGlassPaintHolder))]
[ProtoInclude(400, typeof(BaseSmokePaintHolder)), ProtoInclude(500, typeof(BaseSuspensionPaintHolder)), ProtoInclude(600, typeof(BaseInteriorPaintHolder))]
public abstract class BasePaintHolder
{
[JsonIgnore]
public bool isCustom => this is ICustomPaintHolder;
[JsonIgnore]
public string materialName => CarPaintMaterials.GetName(material);
[JsonIgnore]
public CarPaintType material => materials[materialId];
[ProtoMember(1)]
public int materialId;
protected abstract CarPaintType[] materials { get; }
public BasePaintHolder() { }
public BasePaintHolder(int materialId)
{
this.materialId = materialId;
}
public virtual float GetCategoryCostCoefficient(CarSharedMeta carMeta)
{
return BasePaintItem.DefaultCostCoefficient;
}
public float GetMaterialCostCoefficient(CarSharedMeta carMeta)
{
return carMeta.GetPaintMaterialCostCoefficient(material);
}
public abstract bool Equals(BasePaintHolder other);
}
[ProtoContract]
[ProtoInclude(100, typeof(BodyPaintHolder)), ProtoInclude(200, typeof(BodyCustomPaintHolder))]
public abstract class BaseBodyPaintHolder : BasePaintHolder
{
[ProtoMember(1)]
public BodyPartType part;
protected override CarPaintType[] materials => CarPaintMaterials.Body;
public BaseBodyPaintHolder() { }
public BaseBodyPaintHolder(BodyPartType part, int materialId) : base(materialId)
{
this.part = part;
}
public override float GetCategoryCostCoefficient(CarSharedMeta carMeta)
{
return carMeta.GetPaintCategoryCostCoefficient(part);
}
public abstract BaseBodyPaintHolder Copy();
}
[ProtoContract]
public class BodyPaintHolder : BaseBodyPaintHolder, IPaintHolder
{
[ProtoMember(1)]
public int id { get; set; }
public BodyPaintHolder() { }
public BodyPaintHolder(BodyPartType part, int materialId, int id) : base(part, materialId)
{
this.id = id;
}
public override BaseBodyPaintHolder Copy()
{
return new BodyPaintHolder(part, materialId, id);
}
public override bool Equals(BasePaintHolder other)
{
var otherPaint = other as BodyPaintHolder;
return (otherPaint != null) amp;amp; (otherPaint.part == part) amp;amp; (otherPaint.materialId == materialId) amp;amp; (otherPaint.id == id);
}
}
[ProtoContract]
public class BodyCustomPaintHolder : BaseBodyPaintHolder, ICustomPaintHolder
{
[ProtoMember(1)]
public HSBColor hsb { get; set; }
public BodyCustomPaintHolder() { }
public BodyCustomPaintHolder(BodyPartType part, int materialId, HSBColor hsb) : base(part, materialId)
{
this.hsb = hsb;
}
public override BaseBodyPaintHolder Copy()
{
return new BodyCustomPaintHolder(part, materialId, hsb);
}
public override bool Equals(BasePaintHolder other)
{
var otherPaint = other as BodyCustomPaintHolder;
return (otherPaint != null) amp;amp; (otherPaint.part == part) amp;amp; (otherPaint.materialId == materialId) amp;amp; HSBColor.EqualsOpaque(otherPaint.hsb, hsb);
}
}
[ProtoContract]
[ProtoInclude(100, typeof(WheelPaintHolder)), ProtoInclude(200, typeof(WheelCustomPaintHolder))]
public abstract class BaseWheelPaintHolder : BasePaintHolder
{
[ProtoMember(1)]
public WheelPaintPart part;
protected override CarPaintType[] materials => CarPaintMaterials.Wheel;
public BaseWheelPaintHolder() { }
public BaseWheelPaintHolder(WheelPaintPart part, int materialId) : base(materialId)
{
this.part = part;
}
public abstract BaseWheelPaintHolder Copy();
}
[ProtoContract]
public class WheelPaintHolder : BaseWheelPaintHolder, IPaintHolder
{
[ProtoMember(1)]
public int id { get; set; }
public WheelPaintHolder() { }
public WheelPaintHolder(WheelPaintPart part, int materialId, int id) : base(part, materialId)
{
this.id = id;
}
public override BaseWheelPaintHolder Copy()
{
return new WheelPaintHolder(part, materialId, id);
}
public override bool Equals(BasePaintHolder other)
{
var otherPaint = other as WheelPaintHolder;
return (otherPaint != null) amp;amp; (otherPaint.part == part) amp;amp; (otherPaint.materialId == materialId) amp;amp; (otherPaint.id == id);
}
}
[ProtoContract]
public class WheelCustomPaintHolder : BaseWheelPaintHolder, ICustomPaintHolder
{
[ProtoMember(1)]
public HSBColor hsb { get; set; }
public WheelCustomPaintHolder() { }
public WheelCustomPaintHolder(WheelPaintPart part, int materialId, HSBColor hsb) : base(part, materialId)
{
this.hsb = hsb;
}
public override BaseWheelPaintHolder Copy()
{
return new WheelCustomPaintHolder(part, materialId, hsb);
}
public override bool Equals(BasePaintHolder other)
{
var otherPaint = other as WheelCustomPaintHolder;
return (otherPaint != null) amp;amp; (otherPaint.part == part) amp;amp; (otherPaint.materialId == materialId) amp;amp; HSBColor.EqualsOpaque(otherPaint.hsb, hsb);
}
}
[ProtoContract]
[ProtoInclude(100, typeof(GlassPaintHolder)), ProtoInclude(200, typeof(GlassCustomPaintHolder))]
public abstract class BaseGlassPaintHolder : BasePaintHolder
{
[ProtoMember(1)]
public GlassPaintPart part { get; set; }
protected override CarPaintType[] materials => CarPaintMaterials.Glass;
public BaseGlassPaintHolder() { }
public BaseGlassPaintHolder(GlassPaintPart part, int materialId) : base(materialId)
{
this.part = part;
}
public abstract BaseGlassPaintHolder Copy();
}
[ProtoContract]
public class GlassPaintHolder : BaseGlassPaintHolder, IPaintHolder
{
[ProtoMember(1)]
public int id { get; set; }
public GlassPaintHolder() { }
public GlassPaintHolder(GlassPaintPart part, int materialId, int id) : base(part, materialId)
{
this.id = id;
}
public override BaseGlassPaintHolder Copy()
{
return new GlassPaintHolder(part, materialId, id);
}
public override bool Equals(BasePaintHolder other)
{
var otherPaint = other as GlassPaintHolder;
return (otherPaint != null) amp;amp; (otherPaint.materialId == materialId) amp;amp; (otherPaint.id == id);
}
}
[ProtoContract]
public class GlassCustomPaintHolder : BaseGlassPaintHolder, ICustomPaintHolder
{
[ProtoMember(1)]
public HSBColor hsb { get; set; }
public GlassCustomPaintHolder() { }
public GlassCustomPaintHolder(GlassPaintPart part, int materialId, HSBColor hsb) : base(part, materialId)
{
this.hsb = hsb;
}
public override BaseGlassPaintHolder Copy()
{
return new GlassCustomPaintHolder(part, materialId, hsb);
}
public override bool Equals(BasePaintHolder other)
{
var otherPaint = other as GlassCustomPaintHolder;
return (otherPaint != null) amp;amp; (otherPaint.materialId == materialId) amp;amp; HSBColor.EqualsOpaque(otherPaint.hsb, hsb);
}
}
[ProtoContract]
[ProtoInclude(100, typeof(SmokePaintHolder)), ProtoInclude(200, typeof(SmokeCustomPaintHolder))]
public abstract class BaseSmokePaintHolder : BasePaintHolder
{
protected override CarPaintType[] materials => CarPaintMaterials.Smoke;
public BaseSmokePaintHolder() { }
public BaseSmokePaintHolder(int materialId) : base(materialId) { }
public abstract BaseSmokePaintHolder Copy();
}
[ProtoContract]
public class SmokePaintHolder : BaseSmokePaintHolder, IPaintHolder
{
[ProtoMember(1)]
public int id { get; set; }
public SmokePaintHolder() { }
public SmokePaintHolder(int materialId, int id) : base(materialId)
{
this.id = id;
}
public override BaseSmokePaintHolder Copy()
{
return new SmokePaintHolder(materialId, id);
}
public override bool Equals(BasePaintHolder other)
{
var otherPaint = other as SmokePaintHolder;
return (otherPaint != null) amp;amp; (otherPaint.materialId == materialId) amp;amp; (otherPaint.id == id);
}
}
[ProtoContract]
public class SmokeCustomPaintHolder : BaseSmokePaintHolder, ICustomPaintHolder
{
[ProtoMember(1)]
public HSBColor hsb { get; set; }
public SmokeCustomPaintHolder() { }
public SmokeCustomPaintHolder(int materialId, HSBColor hsb) : base(materialId)
{
this.hsb = hsb;
}
public override BaseSmokePaintHolder Copy()
{
return new SmokeCustomPaintHolder(materialId, hsb);
}
public override bool Equals(BasePaintHolder other)
{
var otherPaint = other as SmokeCustomPaintHolder;
return (otherPaint != null) amp;amp; (otherPaint.materialId == materialId) amp;amp; HSBColor.EqualsOpaque(otherPaint.hsb, hsb);
}
}
[ProtoContract]
[ProtoInclude(100, typeof(SuspensionPaintHolder)), ProtoInclude(200, typeof(SuspensionCustomPaintHolder))]
public abstract class BaseSuspensionPaintHolder : BasePaintHolder
{
[ProtoMember(1)]
public SuspensionPaintPart part { get; set; }
protected override CarPaintType[] materials => CarPaintMaterials.Suspension;
public BaseSuspensionPaintHolder() { }
public BaseSuspensionPaintHolder(SuspensionPaintPart part, int materialId) : base(materialId)
{
this.part = part;
}
public override float GetCategoryCostCoefficient(CarSharedMeta carMeta)
{
return carMeta.GetPaintCategoryCostCoefficient(BodyPartType.Suspension);
}
public abstract BaseSuspensionPaintHolder Copy();
}
[ProtoContract]
public class SuspensionPaintHolder : BaseSuspensionPaintHolder, IPaintHolder
{
[ProtoMember(1)]
public int id { get; set; }
public SuspensionPaintHolder() { }
public SuspensionPaintHolder(SuspensionPaintPart part, int id, int materialId) : base(part, materialId)
{
this.id = id;
}
public override BaseSuspensionPaintHolder Copy()
{
return new SuspensionPaintHolder(part, id, materialId);
}
public override bool Equals(BasePaintHolder other)
{
var otherPaint = other as SuspensionPaintHolder;
return (otherPaint != null) amp;amp; (otherPaint.materialId == materialId) amp;amp; (otherPaint.id == id);
}
}
[ProtoContract]
public class SuspensionCustomPaintHolder : BaseSuspensionPaintHolder, ICustomPaintHolder
{
[ProtoMember(1)]
public HSBColor hsb { get; set; }
public SuspensionCustomPaintHolder() { }
public SuspensionCustomPaintHolder(SuspensionPaintPart part, HSBColor hsb, int materialId) : base(part, materialId)
{
this.hsb = hsb;
}
public override BaseSuspensionPaintHolder Copy()
{
return new SuspensionCustomPaintHolder(part, hsb, materialId);
}
public override bool Equals(BasePaintHolder other)
{
var otherPaint = other as SuspensionCustomPaintHolder;
return (otherPaint != null) amp;amp; (otherPaint.materialId == materialId) amp;amp; HSBColor.EqualsOpaque(otherPaint.hsb, hsb);
}
}
[ProtoContract]
[ProtoInclude(100, typeof(InteriorPaintHolder)), ProtoInclude(200, typeof(InteriorCustomPaintHolder))]
public abstract class BaseInteriorPaintHolder : BasePaintHolder
{
[ProtoMember(1)]
public InteriorPaintPart part { get; set; }
protected override CarPaintType[] materials => CarPaintMaterials.Interior;
public BaseInteriorPaintHolder() { }
public BaseInteriorPaintHolder(InteriorPaintPart part, int materialId) : base(materialId)
{
this.part = part;
}
public override float GetCategoryCostCoefficient(CarSharedMeta carMeta)
{
return carMeta.GetPaintCategoryCostCoefficient(BodyPartType.SeatLeft);
}
public abstract BaseInteriorPaintHolder Copy();
}
[ProtoContract]
public class InteriorPaintHolder : BaseInteriorPaintHolder, IPaintHolder
{
[ProtoMember(1)]
public int id { get; set; }
public InteriorPaintHolder() { }
public InteriorPaintHolder(InteriorPaintPart part, int id, int materialId) : base(part, materialId)
{
this.id = id;
}
public override BaseInteriorPaintHolder Copy()
{
return new InteriorPaintHolder(part, id, materialId);
}
public override bool Equals(BasePaintHolder other)
{
return (other is InteriorPaintHolder otherPaint) amp;amp; (otherPaint.materialId == materialId) amp;amp; (otherPaint.id == id);
}
}
[ProtoContract]
public class InteriorCustomPaintHolder : BaseInteriorPaintHolder, ICustomPaintHolder
{
[ProtoMember(1)]
public HSBColor hsb { get; set; }
public InteriorCustomPaintHolder() { }
public InteriorCustomPaintHolder(InteriorPaintPart part, HSBColor hsb, int materialId) : base(part, materialId)
{
this.hsb = hsb;
}
public override BaseInteriorPaintHolder Copy()
{
return new InteriorCustomPaintHolder(part, hsb, materialId);
}
public override bool Equals(BasePaintHolder other)
{
return (other is InteriorCustomPaintHolder otherPaint) amp;amp; (otherPaint.materialId == materialId) amp;amp; HSBColor.EqualsOpaque(otherPaint.hsb, hsb);
}
}
[ProtoContract]
[ProtoInclude(100, typeof(GenericPaintHolder)), ProtoInclude(200, typeof(GenericCustomPaintHolder))]
public abstract class BaseGenericPaintHolder : BasePaintHolder
{
protected override CarPaintType[] materials => CarPaintMaterials.Generic;
public BaseGenericPaintHolder() { }
public BaseGenericPaintHolder(int materialId) : base(materialId) { }
public abstract BaseGenericPaintHolder Copy();
}
[ProtoContract]
public class GenericPaintHolder : BaseGenericPaintHolder, IPaintHolder
{
[ProtoMember(1)]
public int id { get; set; }
public GenericPaintHolder() { }
public GenericPaintHolder(int materialId, int id) : base(materialId)
{
this.id = id;
}
public override BaseGenericPaintHolder Copy()
{
return new GenericPaintHolder(materialId, id);
}
public override bool Equals(BasePaintHolder other)
{
var otherPaint = other as GenericPaintHolder;
return (otherPaint != null) amp;amp; (otherPaint.materialId == materialId) amp;amp; (otherPaint.id == id);
}
}
[ProtoContract]
public class GenericCustomPaintHolder : BaseGenericPaintHolder, ICustomPaintHolder
{
[ProtoMember(1)]
public HSBColor hsb { get; set; }
public GenericCustomPaintHolder() { }
public GenericCustomPaintHolder(int materialId, HSBColor hsb) : base(materialId)
{
this.hsb = hsb;
}
public override BaseGenericPaintHolder Copy()
{
return new GenericCustomPaintHolder(materialId, hsb);
}
public override bool Equals(BasePaintHolder other)
{
var otherPaint = other as GenericCustomPaintHolder;
return (otherPaint != null) amp;amp; (otherPaint.materialId == materialId) amp;amp; HSBColor.EqualsOpaque(otherPaint.hsb, hsb);
}
}
[ProtoMember(1)]
public List<BaseBodyPaintHolder> bodyPaints = null;
[ProtoMember(2)]
public List<BaseWheelPaintHolder> frontWheelPaints = null;
[ProtoMember(3)]
public List<BaseWheelPaintHolder> rearWheelPaints = null;
[ProtoMember(4)]
public List<BaseSuspensionPaintHolder> suspensionPaints = null;
[ProtoMember(5)]
public BaseGlassPaintHolder glassPaint = null;
[ProtoMember(6)]
public BaseSmokePaintHolder smokePaint = null;
[ProtoMember(14)]
public BaseGenericPaintHolder genericPaint = null;
[ProtoMember(15)]
public List<BaseInteriorPaintHolder> interiorPaints = null;
[ProtoMember(16)]
public List<BaseGlassPaintHolder> lightGlassesPaints = null;
[ProtoMember(7)]
public Dictionary<WheelAxles, int> wheelTires = null;
[ProtoMember(8)]
public List<BodyPartHolder> bodyParts = null;
[ProtoMember(9)]
public int frontRimPartId = 1;
[ProtoMember(10)]
public int rearRimPartId = 1;
[ProtoMember(11)]
public int bodyKitId;
[ProtoMember(12)]
public List<VinylLayer> vinylLayers = null;
[ProtoMember(13)]
public string workshopItemId = null;
public VisualSettings()
{
bodyPaints = new List<BaseBodyPaintHolder>();
rearWheelPaints = new List<BaseWheelPaintHolder>();
frontWheelPaints = new List<BaseWheelPaintHolder>();
suspensionPaints = new List<BaseSuspensionPaintHolder>();
interiorPaints = new List<BaseInteriorPaintHolder>();
lightGlassesPaints = new List<BaseGlassPaintHolder>();
bodyParts = new List<BodyPartHolder>();
vinylLayers = new List<VinylLayer>();
wheelTires = new Dictionary<WheelAxles, int>();
}
public VisualSettings(VisualSettings copyFrom)
{
bodyPaints = new List<BaseBodyPaintHolder>(copyFrom.bodyPaints);
rearWheelPaints = new List<BaseWheelPaintHolder>(copyFrom.rearWheelPaints);
frontWheelPaints = new List<BaseWheelPaintHolder>(copyFrom.frontWheelPaints);
suspensionPaints = new List<BaseSuspensionPaintHolder>(copyFrom.suspensionPaints);
interiorPaints = new List<BaseInteriorPaintHolder>(copyFrom.interiorPaints);
lightGlassesPaints = new List<BaseGlassPaintHolder>(copyFrom.lightGlassesPaints);
bodyParts = new List<BodyPartHolder>(copyFrom.bodyParts);
vinylLayers = new List<VinylLayer>(copyFrom.vinylLayers);
wheelTires = new Dictionary<WheelAxles, int>(copyFrom.wheelTires);
glassPaint = copyFrom.glassPaint;
smokePaint = copyFrom.smokePaint;
genericPaint = copyFrom.genericPaint;
frontRimPartId = copyFrom.frontRimPartId;
rearRimPartId = copyFrom.rearRimPartId;
bodyKitId = copyFrom.bodyKitId;
workshopItemId = copyFrom.workshopItemId;
}
}
Я сгенерировал файл .proto с помощью Serializer.GetProto<VisualSettings>()
и генерирую классы Java (для второго приложения), используя этот файл .proto.
Файл Proto, созданный protobuf-net:
syntax = "proto2";
package visual_settings;
option java_multiple_files = true;
option java_package = "com.test";
option java_outer_classname = "VisualSettingsProto";
message BaseBodyPaintHolder {
optional BodyPartType part = 1 [default = Chassis];
// the following represent sub-types; at most 1 should have a value
optional BodyPaintHolder BodyPaintHolder = 100;
optional BodyCustomPaintHolder BodyCustomPaintHolder = 200;
}
message BaseGenericPaintHolder {
// the following represent sub-types; at most 1 should have a value
optional GenericPaintHolder GenericPaintHolder = 100;
optional GenericCustomPaintHolder GenericCustomPaintHolder = 200;
}
message BaseGlassPaintHolder {
optional GlassPaintPart part = 1 [default = Glasses];
// the following represent sub-types; at most 1 should have a value
optional GlassPaintHolder GlassPaintHolder = 100;
optional GlassCustomPaintHolder GlassCustomPaintHolder = 200;
}
message BaseInteriorPaintHolder {
optional InteriorPaintPart part = 1 [default = SteeringWheelAlcantar];
// the following represent sub-types; at most 1 should have a value
optional InteriorPaintHolder InteriorPaintHolder = 100;
optional InteriorCustomPaintHolder InteriorCustomPaintHolder = 200;
}
message BasePaintHolder {
optional int32 materialId = 1 [default = 0];
// the following represent sub-types; at most 1 should have a value
optional BaseBodyPaintHolder BaseBodyPaintHolder = 100;
optional BaseWheelPaintHolder BaseWheelPaintHolder = 200;
optional BaseGlassPaintHolder BaseGlassPaintHolder = 300;
optional BaseSmokePaintHolder BaseSmokePaintHolder = 400;
optional BaseSuspensionPaintHolder BaseSuspensionPaintHolder = 500;
optional BaseInteriorPaintHolder BaseInteriorPaintHolder = 600;
}
message BaseSmokePaintHolder {
// the following represent sub-types; at most 1 should have a value
optional SmokePaintHolder SmokePaintHolder = 100;
optional SmokeCustomPaintHolder SmokeCustomPaintHolder = 200;
}
message BaseSuspensionPaintHolder {
optional SuspensionPaintPart part = 1 [default = Arm];
// the following represent sub-types; at most 1 should have a value
optional SuspensionPaintHolder SuspensionPaintHolder = 100;
optional SuspensionCustomPaintHolder SuspensionCustomPaintHolder = 200;
}
message BaseWheelPaintHolder {
optional WheelPaintPart part = 1 [default = SpokeFront];
// the following represent sub-types; at most 1 should have a value
optional WheelPaintHolder WheelPaintHolder = 100;
optional WheelCustomPaintHolder WheelCustomPaintHolder = 200;
}
message BodyCustomPaintHolder {
optional HSBColor hsb = 1;
}
message BodyPaintHolder {
optional int32 id = 1 [default = 0];
}
message BodyPartHolder {
optional BodyPartType type = 1 [default = Chassis];
optional int32 id = 2 [default = 0];
}
enum BodyPartType {
Chassis = 0;
BumperFront = 1;
BumperRear = 2;
Skirts = 3;
Doors = 4;
Roof = 5;
Mirrors = 6;
Bonnet = 7;
Trunk = 8;
Spoiler = 9;
LightsFront = 10;
LightsRear = 11;
Exhaust = 12;
Cage = 13;
Suspension = 14;
Interior = 15;
SeatLeft = 16;
SeatRight = 17;
SteeringWheel = 18;
Handbrake = 19;
Shifter = 20;
Dashboard = 21;
Engine = 22;
BlobShadow = 23;
}
message GenericCustomPaintHolder {
optional HSBColor hsb = 1;
}
message GenericPaintHolder {
optional int32 id = 1 [default = 0];
}
message GlassCustomPaintHolder {
optional HSBColor hsb = 1;
}
message GlassPaintHolder {
optional int32 id = 1 [default = 0];
}
enum GlassPaintPart {
Glasses = 0;
FrontLight = 1;
RearLight = 2;
FogLight = 3;
}
message HSBColor {
optional float h = 1 [default = 0];
optional float s = 2 [default = 0];
optional float b = 3 [default = 0];
optional float a = 4 [default = 0];
}
message InteriorCustomPaintHolder {
optional HSBColor hsb = 1;
}
message InteriorPaintHolder {
optional int32 id = 1 [default = 0];
}
enum InteriorPaintPart {
SteeringWheelAlcantar = 0;
SteeringWheelStrings = 1;
SteeringWheelSpokes = 2;
LeftSeatBase = 3;
LeftSeatBottom = 4;
RightSeatBase = 5;
RightSeatBottom = 6;
GearBoxHandle = 7;
HandbrakeHandle = 8;
}
message KeyValuePair_WheelAxles_Int32 {
optional WheelAxles Key = 1;
optional int32 Value = 2;
}
message SmokeCustomPaintHolder {
optional HSBColor hsb = 1;
}
message SmokePaintHolder {
optional int32 id = 1 [default = 0];
}
message SuspensionCustomPaintHolder {
optional HSBColor hsb = 1;
}
message SuspensionPaintHolder {
optional int32 id = 1 [default = 0];
}
enum SuspensionPaintPart {
Arm = 0;
Rack = 1;
Spring = 2;
BrakeCaliper = 3;
}
message VinylLayerSurrogate {
optional int32 rawId = 1 [default = 0];
optional float angle = 2 [default = 0];
optional bool isSymmetry = 3 [default = false];
optional bool isHorizontalFlip = 4 [default = false];
optional bool isVerticalFlip = 5 [default = false];
optional bool isPassThrough = 6 [default = false];
optional bytes colors = 7;
optional bytes transform = 8;
optional int32 groupMask = 9 [default = 0];
optional float clipMaskShift = 10 [default = 0];
}
message VisualSettings {
repeated BasePaintHolder bodyPaints = 1;
repeated BasePaintHolder frontWheelPaints = 2;
repeated BasePaintHolder rearWheelPaints = 3;
repeated BasePaintHolder suspensionPaints = 4;
optional BasePaintHolder glassPaint = 5;
optional BasePaintHolder smokePaint = 6;
repeated KeyValuePair_WheelAxles_Int32 wheelTires = 7;
repeated BodyPartHolder bodyParts = 8;
optional int32 frontRimPartId = 9 [default = 0];
optional int32 rearRimPartId = 10 [default = 0];
optional int32 bodyKitId = 11 [default = 0];
repeated VinylLayerSurrogate vinylLayers = 12;
optional string workshopItemId = 13;
optional BaseGenericPaintHolder genericPaint = 14;
repeated BasePaintHolder interiorPaints = 15;
repeated BasePaintHolder lightGlassesPaints = 16;
}
enum WheelAxles {
Front = 0;
Rear = 1;
}
message WheelCustomPaintHolder {
optional HSBColor hsb = 1;
}
message WheelPaintHolder {
optional int32 id = 1 [default = 0];
}
enum WheelPaintPart {
SpokeFront = 0;
SpokeRear = 1;
RimFront = 2;
RimRear = 3;
}
С помощью сгенерированных классов java я могу десериализовать данные из C# без проблем, но когда я сериализую данные (настройка визуализации) на стороне Java, C# не смог десериализовать их, я получаю ошибку:
ProtoException: No parameterless constructor found for BasePaintHolder
.
Но java может десериализовать собственные сериализованные данные.
Я подозреваю, что шаблон protobuf-net сгенерирован .proto неправильно. Могу ли я улучшить свой файл .proto? Или я делаю что-то не так?
Комментарии:
1. Я думаю, что поддержка полиморфизма-это расширение, и я не уверен, насколько хорошо это поддерживается в Java. Надеюсь, Марк Гравелл увидит это и предоставит более подробную информацию.
2. @JonasH нет, они очень ненадежны и почти никогда не отвечают на вопросы
Ответ №1:
Это происходит из-за наследства, в принципе; наследование-это не концепция, что protobuf поддерживает, так что protobuf-чистая модели наследования через вложенных объектов, чтобы избежать некоторых сложностей при сериализации этого, protobuf-net, который всегда начинается с написания наследование части первая — это так: при сериализации BasePaintHolder
, он может сериализовать поля 400 (суб-тип данных BaseSmokePaintHolder
), затем 1 поле ( materialId
). Это означает, что когда дело доходит до десериализации, у него есть очевидный путь построения, т. Е. К тому времени, когда он получает данные поля, он уже создал окончательный конкретный тип.
Это нормально для сценариев protobuf-net-protobuf-net, но когда мы работаем с одними и теми же данными в Java, он не знает об этом или не заботится об этом и выбирает сериализацию в порядке возрастания полей, т. е. поле 1, затем поле 400. В спецификации явно указано, что поля могут быть не в порядке, но Java может делать все, что захочет.
Итак: теперь мы возвращаем эти данные обратно в protobuf-net, и сначала мы видим поле 1; в этот момент мы понятия не имеем, каким будет окончательный тип, и некуда (пока) вставлять данные. Не имея лучших вариантов, библиотека пытается использовать базовый тип BasePaintHolder
в качестве заполнителя, пока не сможет принимать лучшие решения , но оказывается, что этот тип есть abstract
, так что: даже это не удается.
Итак: вот почему и некоторая предыстория. Что мы можем сделать?
Ну, первое , что мы могли бы попробовать, — это удалить abstract
его, сделав его технически конструктивным. Чтобы предотвратить случайное создание экземпляров внешним кодом, вы также можете создать конструкторы protected
, internal
, или private protected
(что означает пересечение protected
и internal
). Мы также могли бы попробовать использовать SkipConstructor=true
модификатор вкл [ProtoContract]
.
Если это не работает: возможно, необходимо, чтобы в основном работать с 2 различных объектных моделей, одна из которых проста — по сути больше похоже на Java-версии, возможно, выполнив свою схему по https://protogen.marcgravell.com/ — и тот, который имеет наследству; использовать простые версия для десериализации (и при необходимости сериализации, хотя это не должно волновать), а затем повторно отобразить данные в свой собственный код для фактической модели. Другой вариант для меня-найти способ сделать все это волшебным образом и автоматически; что: не маленькая работа.
Комментарии:
1. Спасибо! Способ удаления абстрактных классов работает нормально.