using System; using System.Collections.Generic; using System.IO; using System.Reflection; using MongoDB.Bson; using MongoDB.Bson.IO; using MongoDB.Bson.Serialization; using MongoDB.Bson.Serialization.Attributes; using MongoDB.Bson.Serialization.Options; using MongoDB.Bson.Serialization.Serializers; namespace ET { public class StructBsonSerialize: StructSerializerBase where TValue : struct { public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, TValue value) { Type nominalType = args.NominalType; IBsonWriter bsonWriter = context.Writer; bsonWriter.WriteStartDocument(); FieldInfo[] fields = nominalType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo field in fields) { bsonWriter.WriteName(field.Name); BsonSerializer.Serialize(bsonWriter, field.FieldType, field.GetValue(value)); } bsonWriter.WriteEndDocument(); } public override TValue Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) { //boxing is required for SetValue to work object obj = new TValue(); Type actualType = args.NominalType; IBsonReader bsonReader = context.Reader; bsonReader.ReadStartDocument(); while (bsonReader.ReadBsonType() != BsonType.EndOfDocument) { string name = bsonReader.ReadName(Utf8NameDecoder.Instance); FieldInfo field = actualType.GetField(name,BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { var deserializer = BsonSerializer.LookupSerializer(field.FieldType); deserializer = ApplyRepresentationConfig(deserializer, field); object value = deserializer.Deserialize(BsonDeserializationContext.CreateRoot(bsonReader)); field.SetValue(obj, value); } } bsonReader.ReadEndDocument(); return (TValue) obj; } protected IBsonSerializer ApplyRepresentationConfig(IBsonSerializer deserializer, FieldInfo field) { System.Object[] myAttributes = field.GetCustomAttributes(typeof(BsonRepresentationAttribute), false); if (myAttributes.Length > 0) { // 参考BsonRepresentationAttribute中的Apply的写法,那个方法是个protect的,调用不到 var representationAttr = myAttributes[0] as BsonRepresentationAttribute; if (deserializer is IRepresentationConfigurable configurable) { deserializer = configurable.WithRepresentation(representationAttr.Representation); } if (deserializer is IRepresentationConverterConfigurable converterConfigurable) { RepresentationConverter converter = new RepresentationConverter(representationAttr.AllowOverflow, representationAttr.AllowTruncation); deserializer = converterConfigurable.WithConverter(converter); } } return deserializer; } } }