MongoDB的C#驱动程序类型鉴别与一般类非通用基类继承 [英] MongoDB C# driver type discriminators with generic class inheriting from non-generic base class

查看:330
本文介绍了MongoDB的C#驱动程序类型鉴别与一般类非通用基类继承的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图存储使用官方C#驱动程序从非通用基类继承MongoDB中泛型类的对象的列表。

I'm trying to store a list of objects of a generic class that inherits from a non-generic base class in mongodb using the official C# driver.

我的代码如下所示:

abstract class MyAbstractClass {}

class MyGenericClass<T>: MyAbstractClass
{
    [BsonRequired]
    public List<T> Values = new List<T>();

    public MyGenericClass(IEnumerable<T> values) 
    {
        Values.AddRange(values);
    }
}

class MyContainerClass
{
    [BsonId]
    public string Id;

    [BsonRequired]
    public List<MyAbstractClass> ValueCollections = new List<MyAbstractClass>();

    public MyContainerClass()
    {
        Id = Guid.NewGuid().ToString();
    }
}

在测试中,我创建了一个容器对象并填写与一般的类的实例,就像这样:

When testing, I create a container object and fill it with instances of the generic class, like so:

var container = new MyContainerClass();
container.ValueCollections.Add(new MyGenericClass<string>(new[]{"foo","bar","baz"}));

在我这保存到数据库,文件添加如下所示:

When I save this to the DB, the documents added look like this:

{
"_id": "c5cf5cd1-843f-4d5d-ba8f-5859ae62fd1d",
"ValueCollections": [
    {
        "_t": "MyGenericClass`1",
        "Values": [
            "foo",
            "bar",
            "baz"
        ]
    }
]
}

类型鉴别得到输入MyGenericClass'1而不是MyGenericClass'1 [System.String],这意味着它不可能再反序列化这一点。

The type discriminator gets type "MyGenericClass'1" instead of "MyGenericClass'1[System.String]" which means that it can't possibly deserialize this again.

此外,试图从DB我得到一个错误信息加载这些对象时:无法创建抽象类的实例。但类型鉴别(如果它是正确的),应该让司机看到,它不应该创建的类型MyAbstractClass但MyGenericClass

Also, when trying to load these objects from the DB I get an error message: Instances of abstract classes cannot be created. But the type discriminator (if it were correct) should allow the driver to see that it should not created objects of type MyAbstractClass but of MyGenericClass

所以我的问题是对象:
1.为什么我得到这个错误?
2.为什么它不正确地序列鉴别?

So my questions are: 1. Why do I get this error? 2. Why doesn't it serialize the discriminator correctly?

感谢您的时间。

推荐答案

一些试验后,我发现,你可以编写自己的鉴别约定。我真的不能明白为什么,但默认鉴别惯例似乎使用,而不是全名,这使得它无用的泛型类的类型类的名称属性。

After some experimenting, I found out that you can write your own discriminator conventions. I can't really understand why, but the default discriminator convention seems to use the Name property of the type class, instead of the FullName, which makes it useless for generic classes.

我结束了使用此代码来代替:

I ended up using this code instead:

class FooDiscriminatorConvention : IDiscriminatorConvention
{
    public string ElementName
    {
        get { return "_t"; }
    }

    public Type GetActualType(MongoDB.Bson.IO.BsonReader bsonReader, Type nominalType)
    {
        if(nominalType!=typeof(MyAbstractClass))
            throw new Exception("Cannot use FooDiscriminator for type " + nominalType);

        var ret = nominalType;

        var bookmark = bsonReader.GetBookmark();
        bsonReader.ReadStartDocument();
        if (bsonReader.FindElement(ElementName))
        {
            var value = bsonReader.ReadString();

            ret = Type.GetType(value);

            if(ret==null)
                throw new Exception("Could not find type " + value);

            if(!ret.IsSubclassOf(typeof(MyAbstractClass)))
                throw new Exception("Database type does not inherit from MyAbstractClass.");
        }

        bsonReader.ReturnToBookmark(bookmark);

        return ret;
    }

    public BsonValue GetDiscriminator(Type nominalType, Type actualType)
    {
        if (nominalType != typeof(MyAbstractClass))
            throw new Exception("Cannot use FooDiscriminator for type " + nominalType);

        return actualType.FullName;
    }
}

和以

BsonSerializer.RegisterDiscriminatorConvention(typeof(MyGenericClass<>), new FooDiscriminatorConvention()); //is this needed?
BsonSerializer.RegisterDiscriminatorConvention(typeof(MyAbstractClass), new FooDiscriminatorConvention());



我也不得不做出的基类非抽象,避免会的不克里特实例抽象类错误。这将是很好,能够有一个抽象基类,但由于派生类是通用的,我不能使用BsonKnownTypes。

I also had to make the base class non-abstract, to avoid the "cannot crete instances of abstract classes" error. It would be nice to be able to have an abstract base class, but since the derived class is generic I cannot use BsonKnownTypes.

这篇关于MongoDB的C#驱动程序类型鉴别与一般类非通用基类继承的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆