实现不同类型之间的映射(bool?和enum)使用datcontract
本文关键字:enum datcontract 使用 bool 同类型 之间 映射 实现 | 更新日期: 2023-09-27 18:05:23
我使用DataContract
对用户机器上的对象进行序列化/反序列化。这基本上是一个保存/加载场景。
我有一个DataContract
,它有一个bool?
型的有序DataMember
,现在我需要把它改成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
不保留旧的成员和添加额外的映射属性为每个版本?
试试这个:
[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
会很奇怪,但我认为在你的情况下,它将是其中一个或另一个。
:
看我的另一个答案。在您的示例中,由于布尔值可以很容易地映射到枚举值,因此有一种更简单的方法。
看起来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