c# - 使用 DataContract 实现不同类型(bool?和 enum)之间的映射

标签 c# .net datacontract

我正在使用 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;
        }
    }
}

这基本上应该允许使用旧契约(Contract)和新契约(Contract)的数据进行互操作。如果同时使用 34 就会变得很奇怪,但我认为在您的情况下它会是其中之一。

更新:

查看我的另一个答案。在您的情况下,由于 bool 值可以轻松映射到枚举值,因此有一种更简单的方法。将此答案留给可能没有这种奢侈的人。

关于c# - 使用 DataContract 实现不同类型(bool?和 enum)之间的映射,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31683841/

相关文章:

c# - 程序集特定设置未在运行时加载

c# - 如何避免 "Nested transactions are not supported."错误?

c# - 私有(private)类成员中关键字 'this' 的正确用法是什么?

c# - 为什么WCF代理对象无法访问全局静态对象?

c# - System32 是否仍需要安装屏幕保护程序?

c# - 如何将 AppDomain.CreateDomain 与 AssemblyResolve 一起使用?

c#串口数据丢失

c# - 使用 aspnetcore 2.2 联合 Azure AD 登录后,User.Identity.Name 为空

WCF 客户端在识别 ServiceKnownTypes 时遇到问题?

c# - DataContract + 多维数组——有什么解决方案吗?