2011-11-15 1 views
6

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

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, почему он не может правильно отобразить его?

ответ

9

Водителя должен знать о все дискриминаторе десериализовать любой класс без ошибок. Есть два способа сделать это:

1.Register глобально во время запуска приложения:

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

2.Or хотя BsonKnownTypes: атрибут объявления

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

} 

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

3

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

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

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

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

Ребята, спасибо. Теперь у меня есть дилемма, чей ответ принять –

+2

Ну, ответ Андрея более полный. Должен признаться, я забыл синтаксис вызова «BsonClassMap.RegisterClassMap», и когда я посмотрел его, Андрей уже отправил свой ответ. Я бы предпочел более полный ответ, потому что другие пользователи, вероятно, сначала рассмотрят принятый ответ. – mnemosyn