开发者

Serializing then Deserializing object yielding different results than original object

开发者 https://www.devze.com 2023-03-11 08:05 出处:网络
I\'ll try and provide what information I can, I\'m not entirely sure what would be helpful in understanding this issue.

I'll try and provide what information I can, I'm not entirely sure what would be helpful in understanding this issue.

I noticed I was having some odd behavior on code which I thought should be functionally the same. I am pulling data from Session as it is faster than hitting our database every time, but whenever I save to Session I also save to the database (I can confirm this is 100% true).

I found that, in certain scenarios, I was encountering odd behavior when pulling data from Session, but that I did not encounter this issue when pulling the same data from my database.

//Good:
string data = DashboardDatabaseRepository.Instance.GetWebLayoutData("PaneStates");

if (!string.IsNullOrEmpty(data))
{
    byte[] dataAsArray = System.Convert.FromBase64String(data);
    MemoryStream stream = new MemoryStream(dataAsArray);
    _paneStates = serializer.Deserialize(stream) as SerializableDictionary<string, RadPaneSetting>;
}

//Bad:

if (!object.Equals(DashboardSessionRepository.Instance.GetSession("PaneStates"), null))
{
    _paneStates = DashboardSessionRepository.Instance.GetSession("PaneStates") as SerializableDictionary<string, RadPaneSetting>;
}

Now, I know what it looks like -- I'm doing something weird behind the scenes in my 'GetSession', but all I am doing is this:

public object GetSession( string index )
{
    return HttpContext.Current.Session[index];
}

public void SetSession(string index, object item)
{
    HttpContext.Current.Session[index] = item;
}

Now, here's where things get really weird. The following code turns the 'Bad' code above into 'Good' code.

//WorkAro开发者_开发问答und - Good
get
{
    SerializableDictionary<string, RadPaneSetting> _paneStates = new SerializableDictionary<string, RadPaneSetting>();

    if (!object.Equals(DashboardSessionRepository.Instance.GetSession("PaneStates"), null))
    {
        _paneStates = DashboardSessionRepository.Instance.GetSession("PaneStates") as SerializableDictionary<string, RadPaneSetting>;

        System.IO.MemoryStream memoryStream = new System.IO.MemoryStream();
        System.Xml.Serialization.XmlSerializer xmlSerializer = new System.Xml.Serialization.XmlSerializer(_paneStates.GetType());
        xmlSerializer.Serialize(memoryStream, _paneStates);
        string data = System.Convert.ToBase64String(memoryStream.ToArray());

        if (!string.IsNullOrEmpty(data))
        {
            XmlSerializer serializer = new XmlSerializer(_paneStates.GetType());
            byte[] dataAsArray = System.Convert.FromBase64String(data);// System.Text.Encoding.UTF8.GetBytes(data);
            MemoryStream stream = new MemoryStream(dataAsArray);

            _paneStates = serializer.Deserialize(stream) as SerializableDictionary<string, RadPaneSetting>;
        }
        else
        {
            XmlSerializer serializer = new XmlSerializer(_paneStates.GetType());

            string data = DashboardDatabaseRepository.Instance.GetWebLayoutData("PaneStates");

            if (!string.IsNullOrEmpty(data))
            {
                byte[] dataAsArray = System.Convert.FromBase64String(data);// System.Text.Encoding.UTF8.GetBytes(data);
                MemoryStream stream = new MemoryStream(dataAsArray);
                _paneStates = serializer.Deserialize(stream) as SerializableDictionary<string, RadPaneSetting>;
            }

            DashboardSessionRepository.Instance.SetSession("PaneStates", _paneStates);
        }

    return _paneStates;
}

I'm curious what kind of clean-up could be occurring through serializing and deserializing my object which was retrieved from Session? Is there anything obvious that I am missing here?

Thanks for your time.

EDIT: I believe these two dictionaries have the same data. I looked up a dictionary equality comparer on S.O. and am using the code provided there. Note how the debugger has stepped into the if statement, but the objects on the LHS of the screenshot seem equal. Why would this be occurring?

http://i.stack.imgur.com/ojUPm.png


The problem is that you are using UTF-8 encoding backwards. You are encoding when you think that you are decoding, and decoding when you think that you are encoding.

The UTF-8 encoding is not intended to be used to represent any binary data as a string, it's intended to be used to represent a string as binary data. When you take any binary data and send it though Encoding.UTF8.GetString, you are potentially corrupting the data. It will work for any byte codes that happen to correspond to any character data encoded as UTF-8, but as soon as you get a byte combination that could not exist in UTF-8 encoded data, the method can't convert that into characters. Also, even if you can convert the data into a string without losing data, it's not guaranteed to give the same binary result when you encode the string again.

You should use the base64 encoding instead. Use Convert.ToBase64String to convert binary data into a string representation, and Convert.FromBase64String to get the binary data back:

string data = Convert.ToBase64String(memoryStream.ToArray());

and:

byte[] dataAsArray = Convert.FromBase64String(data);
0

精彩评论

暂无评论...
验证码 换一张
取 消