【问题标题】:How do you serialize value types with MongoDB C# serializer?如何使用 MongoDB C# 序列化程序序列化值类型?
【发布时间】:2016-08-12 14:09:22
【问题描述】:

Mongodb C# 驱动程序不会序列化结构/值类型。如何做到这一点?

【问题讨论】:

    标签: c# mongodb serialization struct value-type


    【解决方案1】:

    您可以使用以下代码创建自定义序列化程序来处理结构:

    public class StructBsonSerializer : IBsonSerializer 
    { 
        public void Serialize(BsonWriter bsonWriter, Type nominalType, object value, IBsonSerializationOptions options) 
        { 
            var fields = nominalType.GetFields(BindingFlags.Instance | BindingFlags.Public); 
            var propsAll = nominalType.GetProperties(BindingFlags.Instance | BindingFlags.Public); 
    
            var props = new List<PropertyInfo>(); 
            foreach (var prop in propsAll) 
            { 
                if (prop.CanWrite) 
                { 
                    props.Add(prop); 
                } 
            } 
    
            bsonWriter.WriteStartDocument(); 
    
            foreach (var field in fields) 
            { 
                bsonWriter.WriteName(field.Name); 
                BsonSerializer.Serialize(bsonWriter, field.FieldType, field.GetValue(value)); 
            } 
            foreach (var prop in props) 
            { 
                bsonWriter.WriteName(prop.Name); 
                BsonSerializer.Serialize(bsonWriter, prop.PropertyType, prop.GetValue(value, null)); 
            } 
    
            bsonWriter.WriteEndDocument(); 
        } 
    
        public object Deserialize(BsonReader bsonReader, Type nominalType, Type actualType, IBsonSerializationOptions options) 
        { 
            var obj = Activator.CreateInstance(actualType); 
    
            bsonReader.ReadStartDocument(); 
    
            while (bsonReader.ReadBsonType() != BsonType.EndOfDocument) 
            { 
                var name = bsonReader.ReadName(); 
    
                var field = actualType.GetField(name); 
                if (field != null) 
                { 
                    var value = BsonSerializer.Deserialize(bsonReader, field.FieldType); 
                    field.SetValue(obj, value); 
                } 
    
                var prop = actualType.GetProperty(name); 
                if (prop != null) 
                { 
                    var value = BsonSerializer.Deserialize(bsonReader, prop.PropertyType); 
                    prop.SetValue(obj, value, null); 
                } 
            } 
    
            bsonReader.ReadEndDocument(); 
    
            return obj; 
        } 
    
        public object Deserialize(BsonReader bsonReader, Type nominalType, IBsonSerializationOptions options) 
        { 
            return Deserialize(bsonReader, nominalType, nominalType, options); 
        } 
    
        public bool GetDocumentId(object document, out object id, out Type idNominalType, out IIdGenerator idGenerator) 
        { 
            throw new NotImplementedException(); 
        } 
    
        public void SetDocumentId(object document, object id) 
        { 
            throw new NotImplementedException(); 
        } 
    } 
    

    然后,为您的结构注册该序列化程序:

    BsonSerializer.RegisterSerializer(typeof(MyStruct), new StructBsonSerializer());
    

    【讨论】:

    • 不错的镜头,虽然它错过了更好的名称匹配。 IE。如果您选择应用骆驼大小写约定,则此代码将不起作用。我会尝试修补它...
    【解决方案2】:

    基于上面的代码,我设法将它适配到 Mongo Driver 2.2.3 版。

    public class BasicStructSerializer<T> : StructSerializerBase<T> where T: struct
    {
        public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, T value)
        {
            var nominalType = args.NominalType;
            var fields = nominalType.GetFields(BindingFlags.Instance | BindingFlags.Public);
            var propsAll = nominalType.GetProperties(BindingFlags.Instance | BindingFlags.Public);
    
            var props = new List<PropertyInfo>();
            foreach (var prop in propsAll)
            {
                if (prop.CanWrite)
                {
                    props.Add(prop);
                }
            }
    
            var bsonWriter = context.Writer;
    
            bsonWriter.WriteStartDocument();
    
            foreach (var field in fields)
            {
                bsonWriter.WriteName(field.Name);
                BsonSerializer.Serialize(bsonWriter, field.FieldType, field.GetValue(value));
            }
            foreach (var prop in props)
            {
                bsonWriter.WriteName(prop.Name);
                BsonSerializer.Serialize(bsonWriter, prop.PropertyType, prop.GetValue(value, null));
            }
    
            bsonWriter.WriteEndDocument();
        }
    
        public override T Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
        {
            //boxing is required for SetValue to work
            var obj = (object)(new T());
            var actualType = args.NominalType;
            var bsonReader = context.Reader;
    
            bsonReader.ReadStartDocument();
    
            while (bsonReader.ReadBsonType() != BsonType.EndOfDocument)
            {
                var name = bsonReader.ReadName();
    
                var field = actualType.GetField(name);
                if (field != null)
                {
                    var value = BsonSerializer.Deserialize(bsonReader, field.FieldType);
                    field.SetValue(obj, value);
                }
    
                var prop = actualType.GetProperty(name);
                if (prop != null)
                {
                    var value = BsonSerializer.Deserialize(bsonReader, prop.PropertyType);
                    prop.SetValue(obj, value, null);
                }
            }
    
            bsonReader.ReadEndDocument();
    
            return (T)obj;
        }
    }
    

    用法:

    cm.GetMemberMap(c => c.SomeMemberName).SetSerializer(new BasicStructSerializer<SomeMemberType>());
    

    【讨论】:

    • 我像BsonSerializer.RegisterSerializer(new BasicStructSerializer&lt;MyValueType&gt;());一样使用它
    猜你喜欢
    • 2022-01-02
    • 2013-09-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多