Сохранять производные объекты с помощью драйвера Mongo C # - PullRequest
5 голосов
/ 12 июня 2011

У меня есть следующая иерархия классов

[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 };
    }
}

, если я сохраняю команду следующим образом:

 Command c = new MoveCommand();
MongoDataBaseInstance.GetCollection<Command>("Commands").Save(c);

, а затем запрашиваю БД, я не вижу сохраненных производных свойств.

{"_id": "4df43312c4c2ac12a8f987e4", "_t": "MoveCommand"}

Я ожидаю, что в качестве ключа в документе будет указано свойство Name.Что я делаю не так?

Кроме того, есть ли способ избежать использования атрибута BsonKnowTypes в базовом классе для сохранения производных экземпляров?Я не понимаю, почему базовый класс должен знать о производных классах.Это плохой ОО-дизайн, который навязывается моей иерархии классов библиотекой BSON.Я что-то здесь упускаю?

1 Ответ

7 голосов
/ 12 июня 2011

1. Name свойство не было сохранено в базе данных, поскольку оно не имеет установщика. Сериализаторы не сериализуют свойства, которые не имеют сеттеров (потому что если сериализатор сериализует такое свойство, он не сможет десериализовать его обратно). Поэтому, если вы хотите сериализовать свойство Name, просто добавьте поддельный сеттер (в ICommand нужно добавить его):

  public override string Name
  {
    get { return "Move Command"; }
    set{}
  }

2.Если вы не хотите использовать атрибут BsonKnownTypes, существует другой способ уведомить сериализатор о известных типах, с которыми он может столкнуться во время десериализации. Просто зарегистрируйте карты один раз, при запуске приложения:

BsonClassMap.RegisterClassMap<MoveCommand>();
//all other inherited from ICommand classes need register here also

Таким образом, вы должны использовать или KnownTypes атрибут или регистр BsonClassMap для каждого полиморфного класса, в противном случае вы получите ошибку 'unknown descriminator' во время десериализации:

  var commands = col.FindAllAs<ICommand>().ToList();

3 Вы сказали:

Это плохой ОО дизайн и сейчас вынужден на моей иерархии классов по Библиотека BSON.

В любом случае, даже без KnownTypes присвойте свой код, используя Bson lib через атрибут BsonId. Если вы хотите избежать этого, вы можете:

   BsonClassMap.RegisterClassMap<MoveCommand>(cm => {
        cm.AutoMap();
        cm.SetIdMember(cm.GetMemberMap(c => c.Id));
    });

Теперь вы можете удалить ссылку на Mongodb.Bson lib из кода вашего домена lib.

...