我试着在Type这一栏做出 Select ,CloudFileTypes就是enum.如果您try 使用Linq方法或MongoDB驱动程序筛选器进行 Select ,则它会将Type视为一个数字,并且无法找到所需的文件,而在数据库的Type字段中,我有string个值.如果我 Select 某个特定的文件并访问类型字段,则它将根据需要返回枚举成员. 如果我误解了,我提前道歉.

代码的问题部分:

public CloudFile GetRoot(User user)
{
    var builder = Builders<CloudFile>.Filter;
    var query = builder.Eq(e => e.Type, CloudFileTypes.Root);
    var root = _fileCollection.Find(query).First();
    
    return root.First();
}

CloudFile型号:

public class CloudFile
    {
        [BsonId]
        [BsonRepresentation(BsonType.ObjectId)]
        public string Id { get; set; }
        [BsonElement("name")] public string Name { get; set; }
        [JsonConverter(typeof(JsonStringEnumConverter))]
        [BsonElement("type")] public CloudFileTypes Type { get; set; }
        [BsonElement("size")] public int Size { get; set; }
        [BsonElement("path")] public string Path { get; set; }
        [BsonRepresentation(BsonType.ObjectId)]
        [BsonElement("user")] public string User { get; set; }
        [BsonRepresentation(BsonType.ObjectId)]
        [BsonElement("parent")] public string Parent { get; set; }
        [BsonRepresentation(BsonType.ObjectId)]
        [BsonElement("childs")] public string[] Childs { get; set; }
    }
    public enum CloudFileTypes
    {
        [EnumMember(Value = "root")] Root,
        [EnumMember(Value = "folder")] Folder,
        [EnumMember(Value = "file")] File,
    }

Example of root file.

我该如何解决这个问题.我试着在谷歌上搜索了一下,没什么用.

#

public class EnumStringConverter<TEnum> : JsonConverter where TEnum: struct, Enum
    {
        public override bool CanConvert(Type objectType)
        {
            return objectType == typeof(CloudFileTypes);
        }
        public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
        {
            if (value is not TEnum @enum)
                return;

            if (!Attribute.IsDefined(@enum.GetType().GetMember(@enum.ToString()).FirstOrDefault(), typeof(EnumMemberAttribute)))
                writer.WriteValue(@enum.ToString());
            writer.WriteValue(EnumExtensions.GetEnumMemberValue(@enum));
        }
        public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer)
        {
            JObject jo = JObject.Load(reader);
            var str = jo.ToString();
            var obj = EnumExtensions.EnumMemberValueToEnum<CloudFileTypes>(str);
            return obj;
        }
    }

推荐答案

这是一个棘手而有趣的问题.

如前所述,根据当前查询MongoDB Fluent API will pass the enum value as an integer而不是EnumMemberAttribute中的字符串值,您将枚举值存储为集合中的字符串.

Warning: This will be a long answer.

这些步骤是为了允许MongoDB fluent API在查询中传递来自EnumMemberAttribute的值.

  1. 一种帮助器/扩展方法,允许您从string转换为Enum(实现EnumMemberAttribute,反之亦然.
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;

public static class EnumExtensions
{
    public static string GetEnumMemberValue<TEnum>(this TEnum @enum)
        where TEnum : struct, Enum
    {
        string enumMemberValue = @enum.GetType()
            .GetMember(@enum.ToString())
            .FirstOrDefault()?
            .GetCustomAttributes<EnumMemberAttribute>(false)
            .FirstOrDefault()?
            .Value;

        if (enumMemberValue == null)
            return @enum.ToString();
            //throw new ArgumentException($"Enum {@enum.GetType().Name} with member {@enum} not apply {nameof(EnumMemberAttribute)} attribute.");

        return enumMemberValue;
    }

    public static TEnum EnumMemberValueToEnum<TEnum>(this string value)
        where TEnum : struct, Enum
    {
        foreach (var field in typeof(TEnum).GetFields())
        {
            if (Attribute.GetCustomAttribute(field,
                typeof(EnumMemberAttribute)) is EnumMemberAttribute attribute)
            {
                if (attribute.Value == value)
                    return (TEnum)field.GetValue(null);
            }

            if (field.Name == value)
                return (TEnum)field.GetValue(null);
        }

        throw new ArgumentException($"{value} is not found.");
    }
}
  1. 实现并注册一个自定义序列化程序,用于将string值(从EnumMemberAttribute值)转换为Enum,反之亦然.参考文献:@wilver's answer on Storing Enums as strings in MongoDB
using MongoDB.Bson.Serialization;
using MongoDB.Bson.Serialization.Attributes;
using MongoDB.Bson.Serialization.Serializers;

public class EnumMemberStringSerializer<TEnum> : ObjectSerializer, IBsonSerializer<TEnum>
    where TEnum : struct, Enum
{
    public new Type ValueType => typeof(TEnum);

    public TEnum Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
    {
        return EnumExtensions.EnumMemberValueToEnum<TEnum>(base.Deserialize(context, args)?.ToString());
    }

    public void Serialize(BsonSerializationContext context, BsonSerializationArgs args, TEnum value)
    {
        base.Serialize(context, args, EnumExtensions.GetEnumMemberValue((TEnum)value));
    }

    public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, object value)
    {
        base.Serialize(context, args, EnumExtensions.GetEnumMemberValue((TEnum)value));
    }

    object IBsonSerializer.Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
    {
        return EnumExtensions.EnumMemberValueToEnum<TEnum>(base.Deserialize(context, args)?.ToString());
    }
}
  1. 注册EnumMemberStringSerializer序列化程序(在创建IMongoDatabase&;IMongoCollection实例之前).
BsonSerializer.RegisterSerializer(typeof(CloudFileTypes), new EnumMemberStringSerializer<CloudFileTypes>());

Csharp相关问答推荐

user32.urltry 从游戏手柄读取输入时引发System. DeliverViolationExcellent

通过C#来自收件箱的互锁Anything模式是否不是线程安全的

将json作为字符串发送到API会导致错误,但发送dotnet对象不会

应用程序启动时出现错误:操作无法同时使用表单和SON主体参数

try 还原包时出错:Dapper已经为System.Data.SQLClient定义了依赖项''''

我需要两个属性类吗

模型绑定RazorPage表单

自动映射程序在GroupBy之后使用项目

如何在Windows 11任务调度程序中每1分钟重复一次任务?

Rx.Net窗口内部可观测数据提前完成

由于POST中的应用程序/JWT,出现不支持的内容类型异常

用C#从Word文档中删除重复的节控件和文本内容控件

try 使用C#ASP.NET收集WMI信息时访问被拒绝,但在PowerShell中工作

在不添加不必要的尾随零的情况下本地化浮点型?

使用带有参数和曲面的注入失败(&Q;)

在DoubleClick上交换DataGridViewImageColumn的图像和工具提示

是否可以将Collectionview中的数组与ObservableCollection绑定?

将C#类导入到PowerShell

无法向Unity注册Microsoft Logger

如果所有";async任务方法()";调用都返回Task.FromResult()-是否同步执行?