Hướng dẫn mongodb enums - mongodb enums

Tôi đã sử dụng CustomEnumSerializer để xử lý thuộc tính EnumMember

public class CustomEnumSerializer : StructSerializerBase, IRepresentationConfigurable> where TEnum : struct
{
    private static readonly Dictionary> _fromValueMap = new Dictionary>(); // string representation to Enum value map

    private static readonly Dictionary> _toValueMap = new Dictionary>(); // Enum value to string map

    // private fields
    private readonly BsonType _representation;

    // constructors
    /// 
    /// Initializes a new instance of the  class.
    /// 
    public CustomEnumSerializer()
        : this((BsonType)0) // 0 means use underlying type
    {
    }

    /// 
    /// Initializes a new instance of the  class.
    /// 
    /// The representation.
    public CustomEnumSerializer(BsonType representation)
    {
        switch (representation)
        {
            case 0:
            case BsonType.Int32:
            case BsonType.Int64:
            case BsonType.String:

                break;

            default:
                var message = string.Format("{0} is not a valid representation for an EnumSerializer.", representation);
                throw new ArgumentException(message);
        }

        // don't know of a way to enforce this at compile time
        var enumTypeInfo = typeof(TEnum).GetTypeInfo();
        if (!enumTypeInfo.IsEnum)
        {
            var message = string.Format("{0} is not an enum type.", typeof(TEnum).FullName);
            throw new BsonSerializationException(message);
        }

        _representation = representation;

        if (representation == BsonType.String)
        {
            var enumType = typeof(TEnum);
            if (!_fromValueMap.ContainsKey(enumType))
            {
                Dictionary fromMap = new Dictionary(StringComparer.InvariantCultureIgnoreCase);
                Dictionary toMap = new Dictionary();

                FieldInfo[] fields = enumType.GetFields(BindingFlags.Static | BindingFlags.Public);

                foreach (FieldInfo field in fields)
                {
                    string name = field.Name;
                    object enumValue = Enum.Parse(enumType, name);

                    // use EnumMember attribute if exists
                    EnumMemberAttribute enumMemberAttrbiute = field.GetCustomAttribute();

                    if (enumMemberAttrbiute != null)
                    {
                        string enumMemberValue = enumMemberAttrbiute.Value;

                        fromMap[enumMemberValue] = enumValue;
                        toMap[enumValue] = enumMemberValue;
                    }
                    else
                    {
                        toMap[enumValue] = name;
                    }

                    fromMap[name] = enumValue;
                }

                _fromValueMap[enumType] = fromMap;
                _toValueMap[enumType] = toMap;
            }
        }
    }

    // public properties
    /// 
    /// Gets the representation.
    /// 
    /// 
    /// The representation.
    /// 
    public BsonType Representation
    {
        get { return _representation; }
    }

    // public methods
    /// 
    /// Deserializes a value.
    /// 
    /// The deserialization context.
    /// The deserialization args.
    /// A deserialized value.
    public override TEnum Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
    {
        var bsonReader = context.Reader;

        var bsonType = bsonReader.GetCurrentBsonType();
        switch (bsonType)
        {
            case BsonType.Int32: return (TEnum)Enum.ToObject(typeof(TEnum), bsonReader.ReadInt32());
            case BsonType.Int64: return (TEnum)Enum.ToObject(typeof(TEnum), bsonReader.ReadInt64());
            case BsonType.Double: return (TEnum)Enum.ToObject(typeof(TEnum), (long)bsonReader.ReadDouble());
            case BsonType.String:
                var fromValue = FromValue(typeof(TEnum), bsonReader.ReadString());
                return (TEnum)Enum.Parse(typeof(TEnum), fromValue.ToString());
            default:
                throw CreateCannotDeserializeFromBsonTypeException(bsonType);
        }
    }

    /// 
    /// Serializes a value.
    /// 
    /// The serialization context.
    /// The serialization args.
    /// The object.
    public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, TEnum value)
    {
        var bsonWriter = context.Writer;

        switch (_representation)
        {
            case 0:
                var underlyingTypeCode = Type.GetTypeCode(Enum.GetUnderlyingType(typeof(TEnum)));
                if (underlyingTypeCode == TypeCode.Int64 || underlyingTypeCode == TypeCode.UInt64)
                {
                    goto case BsonType.Int64;
                }
                else
                {
                    goto case BsonType.Int32;
                }

            case BsonType.Int32:
                bsonWriter.WriteInt32(Convert.ToInt32(value));
                break;

            case BsonType.Int64:
                bsonWriter.WriteInt64(Convert.ToInt64(value));
                break;

            case BsonType.String:
                var val = ToValue(typeof(TEnum), value);
                bsonWriter.WriteString(val);
                break;

            default:
                throw new BsonInternalException("Unexpected EnumRepresentation.");
        }
    }

    private string ToValue(Type enumType, object obj)
    {
        Dictionary map = _toValueMap[enumType];

        return map[obj];
    }
    private object FromValue(Type enumType, string value)
    {
        Dictionary map = _fromValueMap[enumType];

        if (!map.ContainsKey(value))
            return value;

        return map[value];
    }

    /// 
    /// Returns a serializer that has been reconfigured with the specified representation.
    /// 
    /// The representation.
    /// The reconfigured serializer.
    public CustomEnumSerializer WithRepresentation(BsonType representation)
    {
        if (representation == _representation)
        {
            return this;
        }
        else
        {
            return new CustomEnumSerializer(representation);
        }
    }

    // explicit interface implementations
    IBsonSerializer IRepresentationConfigurable.WithRepresentation(BsonType representation)
    {
        return WithRepresentation(representation);
    }
}

0 hữu ích 0 bình luận chia sẻ 0 bình luận chia sẻ