Question

Consider the two classes:

public class Entity
{
    public ObjectId Id { get; set; }
    public E2 e = new E2(ConfigClass.SomeStaticMethod());
}

public class E2
{
    [BsonIgnore]
    public int counter = 5;
    public DateTime last_update { get; set; }

    public E2(int c)
    {
        counter = c;
    }
}

I'll store and then retrieve an object of type Entity to / from a MongoDb like this (assuming collection is empty):

var collection = database.GetCollection<Entity>("temp");
collection.Save<Entity>(new Entity());
var list = collection.FindAs<Entity>(new QueryDocument());
var ent = list.Single();

Regardless of what ConfigClass.SomeStaticMethod() returns, the counter field will be zero (the default value for integers). But if I add a default constructor to the E2 class then counter will be 5.

This means that MongoDb's C# driver has got a problem with calling non-default constructors (which is totally understandable). I know there's a BsonDefaultValue attribute defined within BSON library but it can only accept constant expressions.

What I'm trying to do is to load the default value of a field out of config files while the rest of object is retrieved from MongoDb!? And of course with the least effort.

[UPDATE]

I've also tested this with the same results:

public class Entity
{
    public ObjectId Id { get; set; }
    public E2 e = new E2();
    public Entity()
    {
        e.counter = ConfigClass.SomeStaticMethod();
    }
}

public class E2
{
    [BsonIgnore]
    public int counter = 5;
    public DateTime last_update { get; set; }
}

Running this code results in counter to be zero again!

Was it helpful?

Solution

I managed to accomplish it like this:

public class Entity
{
    public ObjectId Id { get; set; }
    public E2 e = new E2();
}

public class E2 : ISupportInitialize
{
    [BsonIgnore]
    public int counter = 5;
    public DateTime last_update { get; set; }

    public void BeginInit()
    {
    }

    public void EndInit()
    {
        counter = ConfigClass.SomeStaticMethod();
    }
}

The ISupportInitialize interface comes with two methods of BeginInit and EndInit which are called before and after the process of deserialization. They are the best places to set default values.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top