G. *_*sem 3 mongodb mongodb-csharp-2.0 mongodb-.net-driver
我有一个类,其中包含一些我想使用 mongodb 存储的只读属性。
用户.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();
}
}
Run Code Online (Sandbox Code Playgroud)
类映射注册:
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));
});
Run Code Online (Sandbox Code Playgroud)
此类存储为子文档。当我尝试存储整个文档 mongodb 驱动程序告诉我 MongoDB.Bson.BsonSerializationException : Creator 映射类 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);
}
}
Run Code Online (Sandbox Code Playgroud)
编辑
值对象.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();
}
}
Run Code Online (Sandbox Code Playgroud)
用户ID.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();
}
}
Run Code Online (Sandbox Code Playgroud)
看起来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));
});
Run Code Online (Sandbox Code Playgroud)
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);
Run Code Online (Sandbox Code Playgroud)