Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deserialize to self

Ok, I'm probably just having an epic fail here, but my mind wants to say this should work.

Assume DataProtect.DecryptData takes an encrypted string as input and a decrypted string as output. Assume deserializeXML makes the appropriate object and returns it from the newly decrypted string.

So. Why wouldn't this work?

class ArrivedDetails
{
///...

    internal ArrivedDetails(string encrypted)
    {
        this = DataProtect.deserializeXML(DataProtect.DecryptData(encrypted));
    }
///...

Gives me an error of

Cannot assign to '<this>' because it's read only

More specifically,, how can I get this working? I essentially want to decrypt an XML serialized version of the object and then deserialize it within the constructor.

I'm open to "you can't" (with an explanation) as I can put it elsewhere and just assign values, but my mind says something like this should be possible.

like image 990
dotalchemy Avatar asked Mar 22 '11 22:03

dotalchemy


4 Answers

You can archive this with reflection as follows.

var tmp = DataProtect.deserializeXML(DataProtect.DecryptData(encrypted));
foreach (var property in GetType().GetProperties())
    if (property.GetCustomAttributes(typeof (XmlIgnoreAttribute), false).GetLength(0) == 0)
        property.SetValue(this, property.GetValue(tmp, null), null);

This assigns the deserialized object to a temporal variable, and copy the value in each public property to this with reflection. This snippet avoids to copy properties with the XmlIgnore attribute.

like image 183
fujieda Avatar answered Nov 15 '22 22:11

fujieda


No, this is not possible using a constructor, you can't reassign this.

Use a static method instead:

public static ArrivedDetails CreateFromString(string encrypted)
{
    return DataProtect.deserializeXML(DataProtect.DecryptData(encrypted));
}

Call it:

ArrivedDetails details = ArrivedDetails.CreateFromString(encrypted);
like image 37
Femaref Avatar answered Nov 15 '22 21:11

Femaref


You can not assign anything to "this". Change ArriveDetails to a static that return the deserialised object.

class ArrivedDetails
{
    static ArrivedDetails Create(string encrypted)
    { return DataProtect.deserializeXML(...) }
}
like image 21
Richard Schneider Avatar answered Nov 15 '22 22:11

Richard Schneider


What you want is a static factory method that creates the object you require.

class ArrivedDetails
{
///...

    public static ArrivedDetails CreateFromEncryptedKey(string encrypted)
    {
        return DataProtect.deserializeXML(DataProtect.DecryptData(encrypted));
    }
///...

The reason your initial approach didn't work is because this is a private read-only instance field that returns the object from which it is called. You can't write to this.

like image 40
Martin Doms Avatar answered Nov 15 '22 20:11

Martin Doms