当前位置: 首页 > 知识库问答 >
问题:

如何在MongoDB中使用ImmutableArray(C#)?

胡弘毅
2023-03-14

我试图在MongoDB中保存ImmutableArray(System.Collections.Immutable)。

我试过MongoDB。Immutable,但它仅限于Immutable包的旧版本,不支持ImmutableArray。

我试图创建一个自定义序列化程序使用IBsonSeriazer和IBsonSeriazationProviderSeriazerBase没有成功。

[BsonSerializer(typeof(BsonImmutableSerializer<>))]
public class BsonImmutableSerializer<T> : IBsonSerializer<ImmutableArray<T>>
{
    public Type ValueType => typeof(ImmutableArray<T>);

    public object Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
    {
        return context.Reader.ReadString().FromJson<ImmutableArray<T>>().ToImmutableArray();
    }

    public void Serialize(BsonSerializationContext context, BsonSerializationArgs args, object value)
    {
        context.Writer.WriteString(value.ToJson());
    }

    public void Serialize(BsonSerializationContext context, BsonSerializationArgs args, ImmutableArray<T> value)
    {
        context.Writer.WriteString(value.ToJson());
    }

    ImmutableArray<T> IBsonSerializer<ImmutableArray<T>>.Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
    {
        return context.Reader.ReadString().FromJson<ImmutableArray<T>>().ToImmutableArray();
    }
}

或者

public class ImmutableProvider<T> : IBsonSerializationProvider
{
    public IBsonSerializer GetSerializer(Type type)
    {
        return type == typeof(ImmutableList<T>) ? new ImmutableSerializer<T>() : null;
    }
}

public class ImmutableSerializer<T> : SerializerBase<ImmutableList<T>>
{
    public override ImmutableList<T> Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
    {
        return context.Reader.ReadString().FromJson<List<T>>().ToImmutableList();
    }

    public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, ImmutableList<T> value)
    {
        context.Writer.WriteString(value.ToJson());
    }
}

第一个解决方案抛出此错误:

系统运行时。序列化。SerializationException:类型为“System”。收藏。不变的ImmutableArray`1[[System.Int32,mscorlib,Version=4.0.0.0,Culture=neutral,PublicKeyToken=b77a5c561934e089]],数据协定名称为'ArrayFint:http://schemas.microsoft.com/2003/10/Serialization/Arrays”他说。如果您正在使用DATACONTROTSCORALIZER或将未知类型的任何类型添加到已知类型的列表中,请考虑使用DATACONTracTracver,例如,使用NoNyType属性或将它们添加到传递给序列化程序的已知类型的列表中。

第二个投掷:

系统。[0],'System.收藏。不可变。ImmutableArray1[System.Int32]', on'MongoDB. Bson.连载。序列化。2[TValue, TIHT]'违反了类型'TValue'的约束。---


共有1个答案

何高旻
2023-03-14

通常,您将实现EnumerableSerializerBase

using MongoDB.Bson;
using MongoDB.Bson.IO;
using MongoDB.Bson.Serialization;
using MongoDB.Bson.Serialization.Serializers;
using System;
using System.Collections.Generic;

public abstract class ValueEnumerableSerializerBase<TValue, TItem> : SerializerBase<TValue>, IBsonArraySerializer, IBsonSerializer
    where TValue : struct, IEnumerable<TItem>
{
    private readonly Lazy<IBsonSerializer<TItem>> _lazyItemSerializer;

    protected ValueEnumerableSerializerBase()
        : this(BsonSerializer.SerializerRegistry)
    {
    }

    protected ValueEnumerableSerializerBase(IBsonSerializer<TItem> itemSerializer)
    {
        if (itemSerializer == null)
            throw new ArgumentNullException(nameof(itemSerializer));

        _lazyItemSerializer = new Lazy<IBsonSerializer<TItem>>(() => itemSerializer);
    }

    protected ValueEnumerableSerializerBase(IBsonSerializerRegistry serializerRegistry)
    {
        if (serializerRegistry == null)
            throw new ArgumentNullException(nameof(serializerRegistry));

        _lazyItemSerializer = new Lazy<IBsonSerializer<TItem>>(() => serializerRegistry.GetSerializer<TItem>());
    }

    public IBsonSerializer<TItem> ItemSerializer => _lazyItemSerializer.Value;

    public override TValue Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
    {
        if (context == null)
            throw new ArgumentNullException(nameof(context));

        IBsonReader reader = context.Reader;

        BsonType currentBsonType = reader.GetCurrentBsonType();
        switch (currentBsonType)
        {
            case BsonType.Null:
            {
                reader.ReadNull();
                return default;
            }
            case BsonType.Array:
            {
                reader.ReadStartArray();
                object accumulator = CreateAccumulator();
                while (reader.ReadBsonType() != BsonType.EndOfDocument)
                {
                    TItem item = _lazyItemSerializer.Value.Deserialize(context);
                    AddItem(accumulator, item);
                }
                reader.ReadEndArray();
                return FinalizeResult(accumulator);
            }
            default:
            {
                throw CreateCannotDeserializeFromBsonTypeException(currentBsonType);
            }
        }
    }

    public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, TValue value)
    {
        if (context == null)
            throw new ArgumentNullException(nameof(context));

        IBsonWriter writer = context.Writer;

        if (value.Equals(default))
        {
            writer.WriteNull();
        }
        else
        {
            writer.WriteStartArray();
            foreach (TItem item in EnumerateItemsInSerializationOrder(value))
                _lazyItemSerializer.Value.Serialize(context, item);
            writer.WriteEndArray();
        }
    }

    public bool TryGetItemSerializationInfo(out BsonSerializationInfo serializationInfo)
    {
        IBsonSerializer<TItem> itemSerializer = _lazyItemSerializer.Value;
        serializationInfo = new BsonSerializationInfo(null, itemSerializer, itemSerializer.ValueType);
        return true;
    }

    protected abstract void AddItem(object accumulator, TItem item);

    protected abstract object CreateAccumulator();

    protected abstract IEnumerable<TItem> EnumerateItemsInSerializationOrder(TValue value);

    protected abstract TValue FinalizeResult(object accumulator);
}

从这里开始,ImmutableArray的实现

using MongoDB.Bson.Serialization;
using System.Collections.Generic;
using System.Collections.Immutable;

public class ImmutableArraySerializer<T> : ValueEnumerableSerializerBase<ImmutableArray<T>, T>, IChildSerializerConfigurable
{
    public ImmutableArraySerializer()
    {
    }

    public ImmutableArraySerializer(IBsonSerializer<T> itemSerializer)
        : base(itemSerializer)
    {
    }

    public ImmutableArraySerializer(IBsonSerializerRegistry serializerRegistry)
        : base(serializerRegistry)
    {
    }

    public IBsonSerializer WithItemSerializer(IBsonSerializer<T> itemSerializer)
    {
        return new ImmutableArraySerializer<T>(itemSerializer);
    }

    protected override void AddItem(object accumulator, T item)
    {
        ((ImmutableArray<T>.Builder)accumulator).Add(item);
    }

    protected override object CreateAccumulator()
    {
        return ImmutableArray.CreateBuilder<T>();
    }

    protected override IEnumerable<T> EnumerateItemsInSerializationOrder(ImmutableArray<T> value)
    {
        return value;
    }

    protected override ImmutableArray<T> FinalizeResult(object accumulator)
    {
        return ((ImmutableArray<T>.Builder)accumulator).ToImmutable();
    }

    IBsonSerializer IChildSerializerConfigurable.ChildSerializer => ItemSerializer;

    IBsonSerializer IChildSerializerConfigurable.WithChildSerializer(IBsonSerializer childSerializer)
    {
        return new ImmutableArraySerializer<T>((IBsonSerializer<T>)childSerializer);
    }
}

 类似资料:
  • 问题内容: 我的数据库中有大量的文档,我想知道如何浏览所有文档并更新它们,每个文档具有不同的值。 问题答案: 答案取决于您使用的驱动程序。我所知道的所有MongoDB驱动程序都以一种或另一种方式实现。 这里有些例子: mongojs 僧 猫鼬 在回调内部更新文档 在回调内部更新文档的唯一问题是您不知道何时更新所有文档。 要解决此问题,您应该使用一些异步控制流解决方案。以下是一些选项: 异步的 承诺

  • 问题内容: 好的,所以我已经安装了Flask,我想知道如何将MongoDB数据库与即将开始构建的Flask应用程序连接和使用。 问题答案: 我个人发现PyMongo库简单易用。 你首先需要导入并创建一个连接: 然后获取你的数据库实例和集合(表): 然后,你可以通过处理保存数据的JSON文档来操纵数据。他们的网站上有完整的示例。

  • 问题内容: 我遍历了许多博客和网站,了解如何配置Elasticsearch for MongoDB来索引MongoDB中的集合,但是它们都不是直接的。 请向我说明逐步安装Elasticsearch的过程,其中应包括: 组态 在浏览器中运行 我将Node.js与express.js结合使用,因此请相应地提供帮助。 问题答案: 这个答案应该足以使您开始按照本教程使用MongoDB,Elasticsea

  • 本文向大家介绍如何在MongoDB中使用存储的JavaScript?,包括了如何在MongoDB中使用存储的JavaScript?的使用技巧和注意事项,需要的朋友参考一下 它保存在特殊的system.js集合中。为此,请使用db.system.js.save()。以下是语法- 让我们实现以上语法。以下是查询- 以下是调用上述函数以打印实际数据的查询- 这将产生以下输出-

  • 我有一套文件。每个文档有两个字段—“代码”和“状态”。我的mongodb集合包含以下文档: 我想按每个代码的状态查找计数。我想要的输出如下所示: 如何使用spring data mongodb实现这一点?我对mongodb很陌生。 更新我已成功编写mongodb查询。这是: 有人能帮助您在spring data mongodb中编写此查询吗?

  • 问题内容: 我目前正在尝试在mongodb内部的文档数组中提取单个对象。这是一个样本数据集: 我可以在mongo中使用以下命令成功查询: 我无法使用mgo进行相同操作,并尝试了以下操作: 使用嵌套(抛出:合成文字中缺少类型,地图文字中缺少键) 我正在使用httprouter,p.ByName(“ …”)调用是传递给处理程序的参数。 提前致谢。 问题答案: 将与该 方法一起使用,因为doc指出,这使