4

我试图避免在我的数据层和使用该层的客户端代码之间引入任何依赖关系,但是在尝试使用 Mongo 执行此操作时遇到了一些问题(使用 MongoRepository)

MongoRepository 显示了创建反映数据结构的类型并在需要时继承实体的示例。例如。

[CollectionName("track")]
public class Track : Entity  
{
    public string name { get; set; }
    public string hash { get; set; }

    public Artist artist { get; set; }
    public List<Publish> published {get; set;}
    public List<Occurence> occurence  {get; set;}
}

为了在我的客户端代码中使用这些,我想用接口替换特定于 Mongo 的类型,例如:

[CollectionName("track")]
public class Track : Entity, ITrackEntity 
{
    public string name { get; set; }
    public string hash { get; set; }

    public IArtistEntity artist { get; set; }
    public List<IPublishEntity> published {get; set;}
    public List<IOccurenceEntity> occurence  {get; set;}
}

但是,Mongo 驱动程序不知道如何处理这些接口,我可以理解地得到以下错误:

反序列化类 sf.data.mongodb.entities.Track 的艺术家属性时出错:找不到类型 sf.data.IArtistEntity 的序列化程序。---> MongoDB.Bson.BsonSerializationException:找不到类型 sf.data.IArtistEntity 的序列化程序。

有人对我应该如何处理这个问题有任何建议吗?

4

2 回答 2

1

好的 - 所以我找到了我自己问题的答案 - 并认为我会分享以防有人遇到类似问题

我正在寻找的功能是BsonClassMap.RegisterClassMap

这允许您明确定义应该序列化/反序列化域类的哪些属性/字段(注意它取代了任何自动映射 - 您需要定义您希望包含的所有字段/属性)。它解决了反序列化为具有接口类型的属性的问题,没有进一步的问题。

BsonClassMap.RegisterClassMap<Track>(cm =>
{
    cm.MapProperty<IArtistEntity>(c => (IArtistEntity)c.Artist);
    cm.MapProperty<List<IOccurenceEntity>>(c => (List<IOccurenceEntity>)c.Occurence);
    cm.MapProperty(c => c.hash);
    cm.MapProperty(c => c.name);
    cm.MapProperty(c => c.published);

});
于 2012-10-31T22:58:30.660 回答
1

What I did was pretty simple, and I think it would help you out. I had the same question as some of the commenters on the previous answer, so I did a bit more testing on my own. This is working for me.

If you have a concrete type that you're using for the interfaces, you can manually register the serializer that's generated for the concrete type for the interface type.

So in your case.

    BsonSerializer.RegisterSerializer(
        typeof(IPublishEntity), 
        BsonSerializer.LookupSerializer<Publish>());

and

    BsonSerializer.RegisterSerializer(
        typeof(IOccurenceEntity), 
        BsonSerializer.LookupSerializer<Occurence>());

I think it's also important to mention that I'm also manually registering the class maps for my concrete types immediately before registering the serializers. I have tested this method without doing so. I'm not sure if LookupSerializer method would fail if you haven't already done this, but that would look something like this.

    BsonClassMap.RegisterClassMap<Publish>(cm => {
        cm.AutoMap();
    });

and

    BsonClassMap.RegisterClassMap<Occurence>(cm => {
        cm.AutoMap();
    });

Just a cautionary side note that may be worth mentioning, I have not seen this solution anywhere else. Not entirely sure why, but I'm usually a bit skeptical when something that is seemingly obvious doesn't show up on Google's radar anywhere. Hope this helps someone.

于 2015-11-13T06:34:45.207 回答