У класса MongoDB есть аргумент, но ни один из них не настроен - PullRequest
1 голос
/ 09 марта 2020

У меня есть класс с некоторыми свойствами только для чтения, которые я хочу сохранить с помощью mongodb.

User.cs

public class User: ValueObject<User>
    {
        public UserId Id { get; }
        public string Firstname { get; }
        public string Lastname { get; }

        public User(UserId id, string firstname, string lastname)
        {
            Id = new UserId(id.Id);
            Firstname = firstname;
            Lastname = lastname;
        }

        public User(string id, string firstname, string lastname)
        {
            Id = new UserId(id);
            Firstname = firstname;
            Lastname = lastname;
        }

        protected override bool MembersEquals(User other)
        {
            return Id == other.Id && Firstname == other.Firstname && Lastname == other.Lastname;
        }

        protected override int MembersHashCode()
        {
            return Id.GetHashCode() ^ Firstname.GetHashCode() ^ Lastname.GetHashCode();
        }
    }

Регистрация карты классов:

BsonClassMap.RegisterClassMap<User>(cm =>
            {
                cm.AutoMap();
                cm.MapProperty(user => user.Id);
                cm.MapProperty(user => user.Firstname);
                cm.MapProperty(user => user.Lastname);
                cm.MapCreator(user => new User(user.Id, user.Firstname, user.Lastname));
            });

этот класс хранится как поддокумент. когда я пытаюсь сохранить весь документ, драйвер mongodb сообщает мне, что MongoDB.Bson.BsonSerializationException: карта создателя для класса Box.Domain.User имеет 3 аргумента, но ни один из них не настроен. . Я не совсем понял, что это значит.

Примечание: класс UserId имеет зарегистрированный сериализатор

public class UserIdBsonSerializer : SerializerBase<UserId>
    {
        public override UserId Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
        {
            var currentBsonType = context.Reader.GetCurrentBsonType();
            return currentBsonType switch
            {
                BsonType.String => new UserId(context.Reader.ReadString()),
                _ => throw new NotSupportedException($"Cannot deserialize {currentBsonType} to an UserId")
            };
        }

        public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, UserId value)
        {
            context.Writer.WriteString(value.Id);
        }
    }

EDIT

ValueObject.cs

public abstract class ValueObject<T> : IEquatable<T>
        where T : ValueObject<T>
    {
        // Verify the value object members equality.
        protected abstract bool MembersEquals(T other);

        // Generate a hash code depending on the value object members values.
        protected abstract int MembersHashCode();

        #region Equality
        public bool Equals([AllowNull] T other)
        {
            if (ReferenceEquals(other, null))
                return false;

            if (ReferenceEquals(this, other))
                return true;

            return MembersEquals(other);
        }

        public override bool Equals(object obj)
        {
            var other = obj as T;

            return Equals(other);
        }

        public static bool operator ==(ValueObject<T> lhs, ValueObject<T> rhs)
        {
            if (ReferenceEquals(lhs, null) && ReferenceEquals(rhs, null))
                return true;

            if (ReferenceEquals(lhs, null))
                return false;

            return lhs.Equals(rhs);
        }

        public static bool operator !=(ValueObject<T> lhs, ValueObject<T> rhs) => !(lhs == rhs);
        #endregion

        public override int GetHashCode()
        {
            return MembersHashCode();
        }
    }

UserId.cs

public class UserId: ValueObject<UserId>
    {
        public string Id { get; }

        public UserId(string id)
        {
            if (id.Length < 5)
                throw new ArgumentException($"user id must be 5 characters length. {id}");

            // TODO: Add more validation rules for user id

            Id = id;
        }
        protected override bool MembersEquals(UserId other)
        {
            return Id == other.Id;
        }

        protected override int MembersHashCode()
        {
            return Id.GetHashCode();
        }
    }

1 Ответ

0 голосов
/ 09 марта 2020

Похоже, что cm.AutoMap(); в вашей карте классов регистров создает 2 создателей, прежде чем добавлять своих.

Если вы удалите его, он начнет работать.

BsonClassMap.RegisterClassMap<User>(cm =>
            {
                cm.MapProperty(user => user.Id);
                cm.MapProperty(user => user.Firstname);
                cm.MapProperty(user => user.Lastname);
                cm.MapCreator(user => new User(user.Id, user.Firstname, user.Lastname));
            });

Альтернатива было бы удалить ImmutableTypeClassMapConvention из пакета соглашений по умолчанию.

ConventionRegistry.Remove("__defaults__");
var pack = new ConventionPack();
var defaultConventions = DefaultConventionPack.Instance.Conventions;
pack.AddRange(defaultConventions.Except(
    defaultConventions.OfType<ImmutableTypeClassMapConvention>()
    ));
ConventionRegistry.Register(
    "__defaults__",
    pack,
    t => true);
...