msgpack-cli icon indicating copy to clipboard operation
msgpack-cli copied to clipboard

EnumMemberAttribute does not work. (expectedly)

Open aberkromb opened this issue 4 years ago • 0 comments

Hi, we want to use MessagePack in our production and ran into a problem. Current stable version does not work with EnumMemberAttribute. It's important for us. I've wrote some tests for example

public class Tests
    {
        [Fact]
        public void Failed()
        {
            // arrange

            // act
            var firstDto = new DtoWithFirstEnum {Enum = FirstEnum.NotOk};

            var serializerForFirst = MessagePackSerializer.Get<DtoWithFirstEnum>();
            var bytes = serializerForFirst.PackSingleObject(firstDto);

            var serializerForSecond = MessagePackSerializer.Get<DtoWithSecondEnum>();
            var secondDto = serializerForSecond.UnpackSingleObject(bytes);

            // assert 
            Assert.Equal(SecondEnum.SecondValue, secondDto.Enum);
        }

        [Fact]
        public void Pass()
        {
            // arrange

            // act
            var firstDto = new DtoWithFirstEnum {Enum = FirstEnum.NotOk};

            var json = JsonConvert.SerializeObject(firstDto);

            var secondDto = JsonConvert.DeserializeObject<DtoWithSecondEnum>(json);

            // assert 
            Assert.Equal(SecondEnum.SecondValue, secondDto.Enum);
        }
    }

    [DataContract]
    public class DtoWithFirstEnum
    {
        [DataMember(Name = "enum")] public FirstEnum Enum { get; set; }
    }

    [DataContract]
    public class DtoWithSecondEnum
    {
        [DataMember(Name = "enum")] public SecondEnum Enum { get; set; }
    }

    public enum FirstEnum
    {
        [EnumMember(Value = "ok")]
        OK,

        [EnumMember(Value = "not_ok")]
        NotOk
    }

    public enum SecondEnum
    {
        [EnumMember(Value = "ok")]
        FirstValue,

        [EnumMember(Value = "not_ok")]
        SecondValue
    }

Looks like we can refine the EnumMessagePackSerializer class in ctor and add new value ByEnumMember in EnumSerializationMethod


 protected EnumMessagePackSerializer( SerializationContext ownerContext, EnumSerializationMethod serializationMethod )
			: base( ownerContext, SerializerCapabilities.PackTo | SerializerCapabilities.UnpackFrom )
		{
			if ( !typeof( TEnum ).GetIsEnum() )
			{
				throw new InvalidOperationException(
					String.Format( CultureInfo.CurrentCulture, "Type '{0}' is not enum.", typeof( TEnum ) )
				);
			}

			this._serializationMethod = serializationMethod;
			this._underlyingType = Enum.GetUnderlyingType( typeof( TEnum ) );
			var members = Enum.GetValues( typeof( TEnum ) ) as TEnum[];
			this._serializationMapping = new Dictionary<TEnum, string>( members.Length );
			this._deserializationMapping = new Dictionary<string, TEnum>( members.Length );
			foreach ( var member in members )
			{
				var enumName = serializationMethod == EnumSerializationMethod.ByEnumMember
					? GetNameFromEnumMemberAttr( member )
					: member.ToString();
				
				var asString = ownerContext.EnumSerializationOptions.SafeNameTransformer( enumName);
				this._serializationMapping[ member ] = asString;
				this._deserializationMapping[ asString ] = member;
			}
		}

Can you suggest a quick way to solve the problem? Thank you.

aberkromb avatar Oct 16 '19 09:10 aberkromb