实现不同类型之间的映射(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不保留旧的成员和添加额外的映射属性为每个版本?

实现不同类型之间的映射(bool?和enum)使用datcontract

试试这个:

[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;
        }
    }
}

这基本上应该允许使用旧合约和新合约的数据进行互操作。如果同时使用34会很奇怪,但我认为在你的情况下,它将是其中一个或另一个。

:

看我的另一个答案。在您的示例中,由于布尔值可以很容易地映射到枚举值,因此有一种更简单的方法。

看起来boolint32在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