How to deserialize immutable types (pass values from constructor)

1,171 views
Skip to first unread message

Jeffrey Zhao

unread,
Apr 24, 2012, 5:06:21 AM4/24/12
to mongodb...@googlegroups.com
Hi guys,
 
I've some immutable types which has readonly properties which need to be persistent with MongoDB, like:
 
public class Location
{
    public Location(string address, string postCode)
    {
        this.Address = address;
        this.PostCode = postCode;
    }
 
    pubic string PostCode { get; private set; }
    public string Address { get; private set; }
}
 
I can easily save it into mongodb, but how can I tell the driver to create it by constructor when deserializing? Do I have to create my own custom serializer?

Jeffrey Zhao
Blog: http://blog.zhaojie.me/
Twitter: @jeffz_cn (Chinese) | @jeffz_en (English)

craiggwilson

unread,
Apr 24, 2012, 8:08:12 AM4/24/12
to mongodb...@googlegroups.com
Jeff,
  Have you tried this yet?  Technically, when we can't find a no parameters constructor, we use FormatterServices.GetUninitializedObject().  However, you can provide a private constructor with no arguments and we'll use that.

Jeffrey Zhao

unread,
Apr 24, 2012, 10:35:26 AM4/24/12
to mongodb...@googlegroups.com
But the properties still cannot be set – they’re readonly.
 
Jeffrey Zhao
Blog: http://blog.zhaojie.me/
Twitter: @jeffz_cn (Chinese) | @jeffz_en (English)

craiggwilson

unread,
Apr 25, 2012, 8:51:00 AM4/25/12
to mongodb...@googlegroups.com
Have you tried this yet?  The mapping should pickup private setters and use them.  If it does not, please let use know.  However, line 49 of this test shows that it does indeed work:  https://github.com/mongodb/mongo-csharp-driver/blob/master/BsonUnitTests/DefaultSerializer/BsonClassMapTests.cs.  I'd encourage you to create a little program and try this out.

jeffz

unread,
Apr 25, 2012, 9:13:11 AM4/25/12
to mongodb...@googlegroups.com
It's not a solution for me - there maybe no private setters. Only automatic properties have setters.



老赵 ※ Jeffrey Zhao

Sent from my Samsung Galaxy Tab

craiggwilson

unread,
Apr 25, 2012, 10:06:49 AM4/25/12
to mongodb...@googlegroups.com
I'm sorry, but that wasn't clear.  Your sample class above shows private setters.  Could you post a more thorough example of what you need (what your entities look like) and I'll try to answer accordingly.

Jeffrey Zhao

unread,
Apr 25, 2012, 10:38:02 AM4/25/12
to mongodb...@googlegroups.com
Sorry for not being clear...here’s the Location class I want to use:
 
public class Location
{
    private readonly string _postCode;
    private readonly string _address;
 
    public Location(string address, string postCode)
    {
        this._address = address;
        this._postCode = postCode;
    }
 
    pubic string PostCode { get { return this._postCode; } }
 
    public string Address { get; { return this._address; } }
}
 
This class has been defined in an assembly without source code, which means we cannot modify the class (e.g., adding attributes or constructors).
 
I’m now using a custom serializer but it requires quite a lot of code (the real case is not as simple as this one), so I’d like to know is there any support for these scenarios. Like in JSON.NET, we can simply provide a ConstructorHandling (or another name I cannot remember) to handle these kind of cases.

craiggwilson

unread,
Apr 25, 2012, 10:45:04 AM4/25/12
to mongodb...@googlegroups.com
No, there is no current way to deserialize this class.  We do not support creating entities by passing in fields via the constructor.  If the private fields were not readonly, we could handle that scenario.

That being said (and without knowing anything about your constraints), from an architectural perspective, I'd highly suggest insulating yourself from components that are externally controlled.  You could consider it a sort of anti-corruption layer that keeps your domains and logic from getting affected by changes outside of your control.  In other words, create your own Location class that you use everywhere in your own code, and map to the external Location class when you need to interact with it's api.  That way you aren't constrained by decisions outside of your control.

I'm sorry we don't support this currently, but if this type of thing is important to you, please add a feature request to jira (jira.mongodb.org).

Jeffrey Zhao

unread,
Apr 25, 2012, 10:58:53 AM4/25/12
to mongodb...@googlegroups.com
Thanks for your explanation. These immutable models are a set of classes represents a sort of expression tree like .NET build-in ones. They are part of our business models which should be save into mongodb. There would be too much redundant if we define our own mutable models - only because it’s not easy to persistent with data layer.
 
I’ll raise a feature request as well as continue using custom serializer.
 
Thanks.
Reply all
Reply to author
Forward
0 new messages