C# 枚举 DataMember 在 WCF 中更改其值

本文关键字:WCF 枚举 DataMember | 更新日期: 2023-09-27 18:04:27

我有以下代码片段

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

设备状态在客户端 UI 上占有关键部分,
当它被撤防时,它显示为"无法访问"。它仍然可以通过不同的方法从不同的代码区域更新 - 但我不想显示它,只是将其保存在其他地方 - 并在它再次武装时显示最近的状态。
这就是我"不对称"的二传手的原因。
这是 Arm & Disarm 的实现(从客户端调用(

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

我希望我为您提供了您需要的尽可能多的信息。
谢谢
瑙尔。

C# 枚举 DataMember 在 WCF 中更改其值

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

保留 DeviceState 的标准资源库

和 getter,并根据资源库的当前代码实现单独的 SetDeviceState 方法

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

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

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

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

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

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

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

与其问我应该更新这个成员还是另一个成员,不如让二传手为我确定。

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

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