如何使用MongoDB C#serializer序列化值类型?

如何使用MongoDB C#serializer序列化值类型?,c#,mongodb,serialization,struct,value-type,C#,Mongodb,Serialization,Struct,Value Type,Mongodb C#驱动程序不会序列化结构/值类型。如何做到这一点?您可以使用以下代码创建自定义序列化程序来处理结构: public class StructBsonSerializer : IBsonSerializer { public void Serialize(BsonWriter bsonWriter, Type nominalType, object value, IBsonSerializationOptions options) { va

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

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

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(); 
    } 
} 

基于上面的代码,我设法使其适应Mongo驱动程序版本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;
    }
}
公共类BasicStructSerializer:StructSerializerBase其中T:struct
{
public override void Serialize(BsonSerializationContext,BsonSerializationArgs参数,T值)
{
var nominalType=args.nominalType;
var fields=nominalType.GetFields(BindingFlags.Instance | BindingFlags.Public);
var propsAll=nominalType.GetProperties(BindingFlags.Instance | BindingFlags.Public);
var props=新列表();
foreach(propsAll中的var prop)
{
如果(道具可写)
{
道具。添加(道具);
}
}
var bsonWriter=context.Writer;
bsonWriter.WriteStartDocument();
foreach(字段中的变量字段)
{
bsonWriter.WriteName(字段名);
序列化(bsonWriter,field.FieldType,field.GetValue(value));
}
foreach(道具中的var道具)
{
bsonWriter.WriteName(项目名称);
序列化(bsonWriter,prop.PropertyType,prop.GetValue(value,null));
}
bsonWriter.WriteEndDocument();
}
公共重写T反序列化(BsonDeserializationContext,BsonDeserializationArgs args args)
{
//要使SetValue工作,需要装箱
var obj=(object)(新的T());
var actualType=args.NominalType;
var bsonReader=context.Reader;
bsonReader.ReadStartDocument();
while(bsonReader.ReadBsonType()!=BsonType.EndOfDocument)
{
var name=bsonReader.ReadName();
var field=actualType.GetField(名称);
如果(字段!=null)
{
var value=BsonSerializer.Deserialize(bsonReader,field.FieldType);
字段设置值(obj,值);
}
var prop=actualType.GetProperty(名称);
如果(prop!=null)
{
var value=BsonSerializer.Deserialize(bsonReader,prop.PropertyType);
属性设置值(对象,值,空);
}
}
bsonReader.ReadEndDocument();
返回(T)obj;
}
}
用法:

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

这张照片拍得不错,不过没有找到更好的名字匹配。也就是说,如果您选择应用驼峰式套管惯例,则此代码将不起作用。我将尝试修补它…我像使用
BsonSerializer.RegisterSerializer(新的BasicStructSerializer())一样使用它
cm.GetMemberMap(c => c.SomeMemberName).SetSerializer(new BasicStructSerializer<SomeMemberType>());