C# enum DataMember 在 WCF 中更改其值

C# enum DataMember changes its value in WCF

我有以下代码片段

[DataMember]
public StateEnum DeviceState
    {
        get
        {
            return _deviceState;
        }
        set
        {               

            if (IsArmed)
            {
                _deviceState = value;
            }
            else
            {
                _whileDisarmState = value;
            }              
        }
    }

而 IsArmed 是布尔值,
StateEnum 具有以下结构

    [DataContract]
public enum StateEnum
{
    [EnumMember]
    ERROR,
    [EnumMember]
    CONNECTED,
    [EnumMember]
    DISCONNECTED,
    [EnumMember]
    DISARMED,
    [EnumMember]
    ALARM,
    [EnumMember]
    WARNING,

}

我有一个调用服务器并获取对象列表的方法,其中 DeviceState 是其成员之一。 当我在返回列表之前在服务器端中断时,其中一个对象具有 DeviceState = StateEnum.DISCONNECTED 值,
但是当我在客户端中断时,我对同一个对象有 StateEunm.ERROR 值。

我很确定问题出在 IsArmed 布尔值上。 尝试 DataMember 它没有帮助,以及将 [KnownType(typeof(StateEnum))] 添加到对象本身。

还有一件事,这个枚举在客户端是已知的,在添加这个 if 语句之前它工作得很好。

更新

我会尝试用更多的代码片段来解释我的逻辑,
虽然这是复杂的代码,但不确定我是否可以完整地描述它。

以下是相关属性和私有成员:

[DataMember]
    public bool IsArmed
    {
        get { return _isArmed; }
        set { _isArmed = value; }
    }

public StateEnum WhileDisarmState
    {
        get { return _whileDisarmState; }
        set { _whileDisarmState = value; }
    }

#region Private Members

    private StateEnum _deviceState;
    private bool _isArmed;
    private StateEnum _whileDisarmState;

    #endregion

DeviceState 和 WhileDisarmState 在构造函数中获取它们的初始值:

IsArmed = true;    
WhileDisarmState = StateEnum.DISCONNECTED;
DeviceState = StateEnum.DISCONNECTED;

DeviceState 在客户端 UI,
中占有重要地位 撤防时显示为"Unreachable"。 它仍然可以通过不同的方法从不同的代码区域更新 - 但我不想显示它,只是将它保存在其他地方 - 并在它再次武装时显示最近的状态。
这就是我 "not symmetric" setter.
的原因 这是 Arm & Disarm 的实现(从客户端调用)

public virtual void Arm()
    {
        IsArmed = true;
        DeviceState = WhileDisarmState;
        IsUpdated = true;
    }

    public virtual void DisArm()
    {
        DeviceState = StateEnum.DISARMED;
        IsArmed = false;
        IsUpdated = true;
    }

我希望我已经提供了您需要的所有信息。
谢谢,
诺尔.

你看到这种情况是因为你的getter和setter不对称。

似乎 DISCONNECTED 的值被设置在 _whileDisarmState 变量上,使 _deviceState 变量处于其初始状态 default(StateEnum),这恰好是ERROR.

要解决此问题,请将数据传输对象的 getter 和 setter 更改为对称。理想情况下,从它们中删除所有业务逻辑,例如关注 IsArmed 状态。

Instead of asking should I update this member or the other, let the setter determine it for me.

不过,该逻辑不属于 DTO。目前,对象的状态取决于属性设置的顺序。当 控制您设置属性的顺序时,这对于业务对象可能没问题。但是,这对于数据传输对象来说是绝对不能接受的,因为 WCF 实现决定了属性的设置顺序。

例如,考虑传递一个已武装并已连接的对象。如果 WCF 首先设置 IsArmed,然后设置 DeviceState,您最终会得到一个处于连接状态的武装对象(即一切正常)。但是,如果 WCF 首先设置 DeviceState,您最终会得到一个处于错误状态的装备对象,其中 _whileDisarmState 设置为已连接。换句话说,您最终会在传输的另一端得到一个处于 不同 状态的对象,这正是您要解决的问题。

首先,非常重要的一点是,您必须将 实现 合同 分开。

为您的 DeviceState 保留标准 setters 和 getter,并根据您的 setter

的当前代码实现单独的 SetDeviceState 方法

并相应地将所有引用从 DeviceState = 更改为 SetDeviceState

之后,如果需要,如果您有可能构建和测试服务的 "debug" 版本,我建议添加 temporary TraceHelper 属性 对象就像一个简单的字符串,每次更新 DeviceState 和 IsArmed 时都会在追加模式下更新

并且可能还会跟踪所有调用方方法...

以便您可以更轻松地发现更新序列逻辑中是否存在错误..