我正在使用DataContract
来序列化/反序列化用户计算机上的对象。所以基本上是一个保存/加载场景。
我的DataContract
订单DataMember
类型为bool?
,现在我需要将其更改为Enum
。它是有序的,因为其中一个序列化程序是protobuf-net。
现在的样子:
[DataContract]
public class Result
{
[DataMember(Order = 3)]
public bool? Accepted { get; set; }
}
需要:
public enum ResultDecisionStatus
{
Accepted, //// map as 'true' for 'bool?'
Rejected, //// map as 'false' for 'bool?'
Neutral, //// new
Unknown //// map as 'null' for 'bool?'
}
[DataContract]
public class Result
{
[DataMember(Order = 4?)] //// I assume ordering might have to change
public ResultDecisionStatus DecisionStatus { get; set; }
}
我实现了以下似乎是 hacky 但似乎有效。我将Accepted
保持为相同的顺序并将其更改为private
并设置变量以在反序列化时将其映射到新的Enum
。这是好设计吗?这感觉很奇怪。
[DataContract]
public class Result
{
[DataMember(Order = 4)]
public ResultDecisionStatus DecisionStatus { get; set; }
[DataMember(Order = 3)]
private bool? Accepted { get; set; }
[DataMember(Order = 1003)]
private bool AcceptedToDecisionStatusMapped { get; set; }
[OnDeserialized]
private void OnDeserialized(StreamingContext context)
{
if (!AcceptedToDecisionStatusMapped)
{
switch(Accepted)
{
case true:
DecisionStatus = ResultDecisionStatus.Accepted;
break;
case false:
DecisionStatus = ResultDecisionStatus.Rejected;
break;
case null:
DecisionStatus = ResultDecisionStatus.Unknown;
break;
}
AcceptedToDecisionStatusMapped = true;
}
}
}
问题:有没有正确的方法在不保留旧成员并为每个版本添加额外的映射属性的情况下实现有序DataContracts
的类型之间的映射?
答案 0 :(得分:1)
试试这个:
[DataContract]
public class Result
{
private ResultDecisionStatus? _decisionStatus;
[DataMember(Order = 3)]
public bool? Accepted { get; set; }
[DataMember(Order = 4)]
public ResultDecisionStatus DecisionStatus
{
get
{
if (_decisionStatus.HasValue)
{
return _decisionStatus.Value;
}
else if (Accepted.HasValue)
{
return Accepted.Value
? ResultDecisionStatus.Accepted
: ResultDecisionStatus.Rejected;
}
else
{
return ResultDecisionStatus.Unknown;
}
}
set
{
_decisionStatus = value;
}
}
}
这基本上应该允许使用旧合同和新协作的数据进行互操作。如果同时使用了3
和4
,那会很奇怪,但我认为它会在您的情况下成为其中一个。
<强>更新强>:
请参阅我的其他答案。在您的情况下,由于布尔值可以轻松映射到枚举值,因此更简单。将这个答案留给有人可能没有这种奢侈的情况。
答案 1 :(得分:1)
看起来bool
和int32
在protobuf中兼容,所以你可以这样做:
public enum ResultDecisionStatus
{
Rejected = 0, // will catch old boolean false values
Accepted = 1, // will catch old boolean true values
Neutral = 2 // new
}
[DataContract]
public class Result
{
[DataMember(Order = 3)]
public ResultDecisionStatus? DecisionStatus { get; set; }
}
只需使用null
代表Unknown
。