Read-only attributes

Jan 11, 2014 at 8:18 PM
Hello,
I was using Lucifure's SDK to store objects in an Azure Table, and I found the following problem.

We have an object (let’s say type A) with many public readonly fields, some of them are collections (one of them of type A, and a second collection of type B with public readonly fields too).

If the collections are empty, everything is fine and the serialization is fine; otherwise the objects inside the collections are created but populated with null values instead of the original data, so incorrect objects are stored on the data base.

I found out that it was the readonly modifier because I removed it and it worked like a charm.

Is there a reason why the readonly modifiers affects the serialization of objects, ONLY when they are inside collections?

Thanks a lot
Coordinator
Jan 12, 2014 at 1:16 AM
Hello,

I think I understand your question, but just to be sure can you include an example of the object you are attempting to write to the Azure table.

Thanks!
Jan 12, 2014 at 4:40 PM
public class Resource
{
    [StashRowKey]
    public readonly string resourceIdentifier;

    [Stash]
    public readonly string resourceName;

    [StashCollection]
    public readonly List<Resource> Resources;

    [Stash]
    public readonly long size;

    [Stash]
    public readonly string shareLink;

    [Stash]
    public readonly ResourceType ResourceType;

    [StashCollection]
    public readonly List<Tag> Tags;

    [StashPartitionKey]
    public int ownerId;
}

And the proper empty constructor and normal constructor
Coordinator
Jan 12, 2014 at 8:14 PM
Thanks for posting the code. It confirms my understanding.

Ideally, Lucifure Stash should have detected that the member is a readonly and expose an error. It would have made debugging much easier.

I am assuming that Internally, the reflection set method does nothing in the case of readonly fields and so the data in the collection was not being updated but no exception was thrown.

I think, usually this is be an easy defect to spot (as you did) and fix. If more people run into this issue, I will update the code to expose an error.

Thanks for taking the time to report this oversight! I appreciate it.
Jan 12, 2014 at 8:39 PM
Thanks a lot for your fast reply.
So if in my model the Resource attributes are set as read-only therefore I cannot store them through Lucifure? The only solution is to change my model and delete the read-only attribute of the fields?
Coordinator
Jan 12, 2014 at 8:45 PM
Correct!
The underlying reflections support does not seem to allow readonly fields to be updated.
Jan 12, 2014 at 8:52 PM
Hi!

Can't you set the value of that fields even if they are read only? Because that can be done via reflection (you are even doing that now, because de "root" object is correctly populated).

Thanks!
Jan 12, 2014 at 8:57 PM
Edited Jan 12, 2014 at 8:59 PM
I put you this case

Object 1)

I have an instance of Resource with Tags, and resources (the collections) empty, with readonly fields, and it is correctly populated

Object 2)


I have an instance of Resource with Tags, and resources (the collections) NON empty, with readonly fields.
The object is correctly populated, but the "nested objects" inside the collections are only populated on their non readonly fields

What is the difference on a code-base level to set up Object 1) fields and Object 2) fields?

Thanks a lot for the rapid responses!
Coordinator
Jan 12, 2014 at 9:03 PM
If you mean the collection as the root object, it is probably created by the default constructor.

So in the above example the default constructor is probably doing a
Tags = new List<Tag>();
Jan 12, 2014 at 9:16 PM
My root object is the class Resource. it contains two collections one of them of Resources.

The root object is populated correctly, but the Resource objects inside the collection are not, only the non read only fields are populated.
Coordinator
Jan 12, 2014 at 9:55 PM
Hi Sebastrian,

I guess in my hurry I misunderstood and only after running tests myself, I realized that readonly is supported by Lucifure stash.

However, the underlying objects in the collection are not serialized by Lucifure but rather by the data contract serializer.

It seems that if you annotate your readonly object with [DataMember], the data contract serializer will serialize it.
However, you will also need to annotate all other fields too and the class itself with [DataContract].

Something like this
    [DataContract]
    public 
    class Resource
    {
            [DataMember]
            public 
            string                              A;

            [DataMember]
            public 
            readonly 
            string                              B;

        public 
        Resource()
        {
        }

        public 
        Resource(
            string                              a,
            string                              b)
        {
            A = a;
            B = b;
        }
    }
Let me know if this works for you.
Jan 19, 2014 at 2:37 PM
It works!
Thank you very much for your help