Abh*_*tel 5 mongodb mongodb-.net-driver
我有以下类层次结构
[BsonKnownTypes(typeof(MoveCommand))]
public abstract class Command : ICommand
{
public abstract string Name
{
get;
}
public abstract ICommandResult Execute();
}
public class MoveCommand : Command
{
public MoveCommand()
{
this.Id = ObjectId.GenerateNewId().ToString();
}
[BsonId]
public string Id { get; set; }
public override string Name
{
get { return "Move Command"; }
}
public override ICommandResult Execute()
{
return new CommandResult { Status = ExecutionStatus.InProgress };
}
}
Run Code Online (Sandbox Code Playgroud)
如果我像这样保存命令:
Command c = new MoveCommand();
MongoDataBaseInstance.GetCollection<Command>("Commands").Save(c);
Run Code Online (Sandbox Code Playgroud)
然后查询数据库,我没有看到派生属性持久化.
{"_ id":"4df43312c4c2ac12a8f987e4","_ t":"MoveCommand"}
我希望Name属性作为文档中的键.我究竟做错了什么?
另外,有没有办法避免在基类上使用BsonKnowTypes属性来持久化派生实例?我没有看到基类需要知道派生类的原因.这是糟糕的OO设计,并且被BSON库强制在我的类层次结构上.我在这里错过了什么吗?
1. Name属性未保存到数据库中,因为它没有设置器.序列化程序不会序列化没有设置器的属性(因为如果序列化程序序列化这样的属性,它将无法将其反序列化).所以,如果你想要序列化Name属性,那么只需添加假的setter(ICommand需要添加它):
public override string Name
{
get { return "Move Command"; }
set{}
}
Run Code Online (Sandbox Code Playgroud)
2.如果您不想使用BsonKnownTypes属性,则有另一种方法可以通知序列化程序在反序列化期间可能遇到的已知类型.在app start事件上只需注册一次地图:
BsonClassMap.RegisterClassMap<MoveCommand>();
//all other inherited from ICommand classes need register here also
Run Code Online (Sandbox Code Playgroud)
所以你应该使用或KnownTypes属性或注册BsonClassMap每个多态类,否则你会在反序列化过程中得到"未知的descriminator"错误:
var commands = col.FindAllAs<ICommand>().ToList();
Run Code Online (Sandbox Code Playgroud)
3你说:
这是糟糕的OO设计,并且被BSON库强制在我的类层次结构上.
在任何情况下,即使没有KnownTypes使用Bson lib通过BsonId属性来分配您的代码.如果你想避免它,你可以:
BsonClassMap.RegisterClassMap<MoveCommand>(cm => {
cm.AutoMap();
cm.SetIdMember(cm.GetMemberMap(c => c.Id));
});
Run Code Online (Sandbox Code Playgroud)
所以现在你可以Mongodb.Bson从你的域代码库中删除对lib的引用.
| 归档时间: |
|
| 查看次数: |
3933 次 |
| 最近记录: |