简体   繁体   中英

How can I specify the constructor to use for MongoDB deserialization without using attributes (C#)

Note: I'm using the MongoDB C# Driver 2.0

I would like to replicate the behaviour of the BsonConstructor attribute but using the BsonClassMap API.

Something like this:

BsonClassMap.RegisterClassMap<Person>(cm =>
{
    cm.AutoMap();
    cm.MapCreator(p => new Person(p.FirstName, p.LastName));
});

but without having to specify each argument.

The reason I want to do it this way is that I don't want to "pollute" my domain model with implementation concerns.

I have found this (SetCreator)

BsonClassMap.RegisterClassMap<Person>(cm =>
{
    cm.AutoMap();
    cm.SetCreator(what goes here?);
});

but I don't know how to use the SetCreator function, and if it does what I think it does...

I achived the same result using the conventions instead of BsonClassMap

Here is an example (reading (serialization) from read only public properties and writing (deserialization) to the constructor)

public class MongoMappingConvention : IClassMapConvention
    {
        public string Name
        {
            get { return "No use for a name"; }
        }

        public void Apply(BsonClassMap classMap)
        {
            var nonPublicCtors = classMap.ClassType.GetConstructors(BindingFlags.NonPublic | BindingFlags.Instance);

            var longestCtor = nonPublicCtors.OrderByDescending(ctor => ctor.GetParameters().Length).FirstOrDefault();

            classMap.MapConstructor(longestCtor);

            var publicProperties = classMap.ClassType.GetProperties(BindingFlags.Public | BindingFlags.Instance)
                .Where(p => p.CanRead);

            foreach (var publicProperty in publicProperties)
            {
                classMap.MapMember(publicProperty);
            }
        }
    }

Old question, I know, but something like this worked for me with MongoDB driver 2.10.4:

    var mapper = new BsonClassMap(type);
    mapper.AutoMap();

    var constructorInfo = type.GetConstructor(...); // Find the constructor you want to use
    mapper.MapConstructor(constructorInfo, new[] {"FirstName", "LastName"});

Note that the array passed to MapConstructor has the property names, not the constructor argument names. As I understand, it goes by the order of constructor arguments, but they may have different names, eg

public Person(string givenName, string surname)
{
    FirstName = givenName;
    LastName = surname;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM