I am trying to register class maps using MongoDb's C# driver. In my case I have a number of classes which derive from a base class. All have constructors which require parameters, and their properties are get-only. Interestingly, MongoDb throws an error when mapping a derived class of this kind unless its properties at least have a private setter.
See below for a minimal way to reproduce the exception in question, which occurs during configuration in startup:
public class Base
{
public Base(int myBaseProperty)
{
MyBaseProperty = myBaseProperty;
}
public int MyBaseProperty { get; }
}
public class Derived : Base
{
public Derived(int myBaseProperty, string myDerivedProperty) : base(myBaseProperty)
{
MyDerivedProperty = myDerivedProperty;
}
public string MyDerivedProperty { get; }
}
public class DerivedWithSetter : Base
{
public DerivedWithSetter(int myBaseProperty, string myDerivedProperty) : base(myBaseProperty)
{
MyDerivedProperty = myDerivedProperty;
}
public string MyDerivedProperty { get; private set; }
}
**IN STARTUP**
BsonClassMap.RegisterClassMap<Base>(cm =>
{
cm.AutoMap();
cm.MapCreator(b => new Base(b.MyBaseProperty));
});
BsonClassMap.RegisterClassMap<DerivedWithSetter>(cm =>
{
cm.AutoMap();
cm.MapCreator(d => new DerivedWithSetter(d.MyBaseProperty, d.MyDerivedProperty));
});
BsonClassMap.RegisterClassMap<Derived>(cm =>
{
cm.AutoMap();
cm.MapCreator(d => new Derived(d.MyBaseProperty, d.MyDerivedProperty));
});
This results in the following ArgumentOutOfRangeException when run:
The memberInfo argument must be for class Derived, but was for class Base. (Parameter 'memberInfo')
Specifically, the exception occurs when the class Derived is mapped, while DerivedWithSetter (identical aside from the private set) is mapped properly.
Primarily, I am curious why this is the case, and how I may resolve the issue (I wouldn't want to have to add private set to all my properties just so that database mapping works).
Am I using the driver in an unintended way? Or is there some other explanation?
Edit
If I change the constructor of Derived to not require an argument to be passed on to the base class, then the exception no longer occurs. For example:
public Derived(string myDerivedProperty) : base(2)
{
MyDerivedProperty = myDerivedProperty;
}
Here the literal value 2 is passed to the base constructor instead of an argument int myBaseProperty. In this case there is no exception. This might indicate then that it has something to do with how MongoDb evaluates constructors of derived classes when automapping properties. The addition of a private setter may be "solving" the issue simply by allowing MongoDb to completely circumvent the constructor. Is this intended behavior though, or should MongoDb hypothetically be able to automap via constructors in this way?