MongoDB doesn’t serialise C# read-only properties

C# 6 introduced getter-only auto-properties, which are a great way of conveying immutability for your classes. However, by default MongoDB ignores these properties from its class maps, as it can’t deserialise them back into a class.

To automatically map read-only properties, you can use a custom convention:

/// <summary>
/// A convention to ensure that read-only properties are automatically mapped (and therefore serialised).
/// </summary>
public class MapReadOnlyPropertiesConvention : ConventionBase, IClassMapConvention
    private readonly BindingFlags _bindingFlags;

    public MapReadOnlyPropertiesConvention() : this(BindingFlags.Instance | BindingFlags.Public) {}

    public MapReadOnlyPropertiesConvention(BindingFlags bindingFlags)
        _bindingFlags = bindingFlags | BindingFlags.DeclaredOnly;

    public void Apply(BsonClassMap classMap)
        var readOnlyProperties = classMap
            .Where(p => IsReadOnlyProperty(classMap, p))

        foreach (var property in readOnlyProperties)

    private static bool IsReadOnlyProperty(BsonClassMap classMap, PropertyInfo propertyInfo)
        if (!propertyInfo.CanRead) return false;
        if (propertyInfo.CanWrite) return false; // already handled by default convention
        if (propertyInfo.GetIndexParameters().Length != 0) return false; // skip indexers

        var getMethodInfo = propertyInfo.GetMethod;

        // skip overridden properties (they are already included by the base class)
        if (getMethodInfo.IsVirtual && getMethodInfo.GetBaseDefinition().DeclaringType != classMap.ClassType) return false;

        return true;

And then register the convention on startup:

var conventionPack = new ConventionPack
    new MapReadOnlyPropertiesConvention()

ConventionRegistry.Register("Conventions", conventionPack, _ => true);

This will ensure that read-only properties are serialised, which is all we needed. However, to then deserialise properties back into a class, you may need a constructor. You can find an extended example of this at (which this code is based on) – we had constructor chains that this didn’t seem to work with, but it might help guide you further.

3 Replies to “MongoDB doesn’t serialise C# read-only properties”

  1. Björn’s suggestion is useful for only assigned properties by constructor. That method is useless for other properties. Your class is working as expected. Viva reflection 🙂 I was gonna try the similar somethings but i found yours. Thanks for your help

  2. Thanks for this, although it seems this has been built in.

    This code works for me:

    BsonClassMap.RegisterClassMap<Document>(cm => { cm.AutoMap(); new ImmutableTypeClassMapConvention().Apply(cm); });

    1. Thanks for the tip Björn, perhaps I missed that when searching, or it was only available in a later version of MongoDB!

Something to add?

This site uses Akismet to reduce spam. Learn how your comment data is processed.