Хранение словаря с полиморфными значениями в mongoDB с использованием C # - PullRequest
6 голосов
/ 15 ноября 2011

Допустим, у нас есть ключ со значениями, которые по своему смыслу полиморфны. Рассмотрим следующий пример проекта:

public class ToBeSerialized
{
    [BsonId]
    public ObjectId MongoId;
    public IDictionary<string, BaseType> Dictionary;
}

public abstract class BaseType
{
}

public class Type1 : BaseType
{
    public string Value1;
}

public class Type2:BaseType
{
    public string Value1;
    public string Value2;
}


internal class Program
{
    public static void Main()
    {
        var objectToSave = new ToBeSerialized
                               {
                                   MongoId = ObjectId.GenerateNewId(),
                                   Dictionary = new Dictionary<string, BaseType>
                                                    {
                                                        {"OdEd1", new Type1 {Value1="value1"}},
                                                        {
                                                            "OdEd2",
                                                            new Type1 {Value1="value1"}
                                                            }
                                                    }
                               };
        string connectionString = "mongodb://localhost/Serialization";
        var mgsb = new MongoUrlBuilder(connectionString);
        var MongoServer = MongoDB.Driver.MongoServer.Create(mgsb.ToMongoUrl());
        var MongoDatabase = MongoServer.GetDatabase(mgsb.DatabaseName);
        MongoCollection<ToBeSerialized> mongoCollection = MongoDatabase.GetCollection<ToBeSerialized>("Dictionary");
        mongoCollection.Save(objectToSave);

        ToBeSerialized received = mongoCollection.FindOne();
    }
}

Иногда, когда я пытаюсь десериализовать его, я получаю ошибки десериализации, такие как «Неизвестное значение дискриминатора« Имя конкретного типа »». Что я делаю неправильно? Если каждое значение хранит _t, почему оно не может правильно отобразить его?

Ответы [ 2 ]

9 голосов
/ 15 ноября 2011

Драйвер должен знать обо всех дискриминаторах, чтобы десериализовать любой класс без ошибок. Есть два способа сделать это:

1. Зарегистрируйте его глобально при запуске приложения:

BsonClassMap.RegisterClassMap<Type1>();
BsonClassMap.RegisterClassMap<Type2>();

2. Или через BsonKnownTypes attibute:

[BsonKnownTypes(typeof(Type1), typeof(Type2)]
 public class BaseType
 {

 }

Если вы будете использовать # 1 или # 2, ваша десериализация будет работать правильно.

3 голосов
/ 15 ноября 2011

Вы должны зарегистрировать, какие типы наследуются от BaseClass, прежде чем пытаться десериализовать их. Это произойдет автоматически, если вы сначала сериализуетесь, поэтому, вероятно, ошибка возникает только иногда.

Вы можете зарегистрировать производные типы, используя атрибут:

[BsonDiscriminator(Required = true)]
[BsonKnownTypes(typeof(DerivedType1), typeof(DerivedType2))]
public class BaseClass { ... }

public class DerivedType1 : BaseClass { ... }
...