0

My domain model objects mostly have private fields where their state is modified by atomic methods that enforce invariants. I'd really rather not use private properties and keep them as fields.

Is there a way to configure RavenDb to include private fields in its serialization?

I think what I want is something similar to what's described in this post for JSON.Net library which I think RavenDb uses under the hood, but I cannot see a way to implement what's described.

I can see there is this:

docStore.Conventions.CustomizeJsonSerializer

But I still can't figure out where to instruct it to include fields?

Community
  • 1
  • 1
David Masters
  • 8,069
  • 2
  • 44
  • 75
  • 2
    This one is old, but might help you: https://dotbrand.wordpress.com/2010/07/05/entities-with-privateprotected-setters-in-ravendb/ Ayende wrote that you can do it by implementing a custom `JsonContractResolver` – Alexey Zimarev Mar 19 '16 at 14:16
  • Thanks @AlexeyZimarev - that post was really useful. – David Masters Mar 19 '16 at 19:07
  • Note that with serializing domain objects directly, you're constraining your domain model significantly. You have persistence concerns in your domain model (or will have soon if you don't have them yet). You might want to consider creating a persistence model and analyze the trade-off before making this decision. – theDmi Mar 21 '16 at 13:13
  • @theDmi I have had this problem previously with using ORMs and normally use seperate objects for the a data access layer. But with using a document database, I'm not sure there are any constraints? At least I'm yet to find any with RavenDb? – David Masters Mar 21 '16 at 13:33
  • There are quite a few! Document versioning and migration management are among the more common concerns that can be fully implemented in a persistence model. Other examples include circular dependencies in the domain model (which need to be broken up for persistence), conversions (e.g. for dates) and performance related stuff (e.g. query optimization). – theDmi Mar 21 '16 at 13:50
  • Yeah, I take your point about versioning & migration management.The circular dependencies thing I'm not sure I see as an issue though? I'd want to avoid them to start with, but If there was a need I can configure the serialization to ignore a particular field for a given type. What do you mean by conversions? Not sure about query optimisation either? I only expect to fetch aggregates by their ID. Any queries will be done against indexes? – David Masters Mar 22 '16 at 12:23
  • In the current project, we needed to put certain properties in a different form on the document than it had in the aggregate to support efficient queries. I know, you can get away without a persistence model, some projects do that successfully. It's just a trade-off that you should consider carefully, that's all I wanted to point out. – theDmi Mar 23 '16 at 09:04
  • Ok, well thanks for your input; it has got me thinking - particularly about versioning & migration. – David Masters Mar 23 '16 at 09:10

1 Answers1

3

Following Alexey's suggested post pointed me in the right direction, the post actually uses a deprecated property - this is how I've done it:

public class IncludeNonPublicMembersContractResolver : DefaultContractResolver
{
    protected override List<MemberInfo> GetSerializableMembers(Type type)
    {
        var members = new List<MemberInfo>();

        members.AddRange(type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance));
        members.AddRange(type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance));

        return members;
    }
}

docStore.Conventions.JsonContractResolver = new IncludeNonPublicMembersContractResolver();
David Masters
  • 8,069
  • 2
  • 44
  • 75