Search code examples
c#wcfenumsdatamember

C# enum DataMember changes its value in WCF


I have the following code snippet

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

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

while IsArmed is Boolean,
and StateEnum has the following struct

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

}

I have a method which invokes the server and get list of objects, which DeviceState is one of its members. When I break on server side just before returning the list, one of the objects have a DeviceState = StateEnum.DISCONNECTED value,
but when I break on the client side, I have for the same object the StateEunm.ERROR value.

I'm pretty sure the problem is with the IsArmed Boolean. Trying to DataMember it didn't help, as well as adding [KnownType(typeof(StateEnum))] to the object itself.

One more thing, this enum is known on client side, it worked perfectly fine before adding this if statement.

Update

I'll try to explain my logic with more code snippets,
though this is complex code, not sure I can describe it fully.

Here are the relevant properties and private members:

[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 get their initial value in the constructor:

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

DeviceState holds crucial part on client UI,
It is displayed as "Unreachable" when it is disarmed. It can still be updated from different areas of code, by different methods - but I don't want to display it, just save it somewhere else - and display the recent state when it is armed again.
This is the reason for my "not symmetric" setter.
Here is the implementation for the Arm & Disarm (invoked from client side)

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

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

I hope I gave you as much info as you need.
Thanks,
Naor.


Solution

  • A first, very important point is that you have to separate the implementation from the contract.

    Keep the standard setters and getters for your DeviceState and implement a separate SetDeviceState method based on the current code of your setter

    and change all the references accordingly from DeviceState = to SetDeviceState

    After that, in case of need, if you have the possibility to build and test a "debug" version of your service I'd suggest to add a temporary TraceHelper property to the object like a simple string that is updated in append mode each time DeviceState and IsArmed are updated

    and possibly tracking also all the caller methods...

    so that you can more easily spot if there has been a bug in the update sequence logic..