jefffhaynes / BinarySerializer

A declarative serialization framework for controlling formatting of data at the byte and bit level using field bindings, converters, and code.
MIT License
290 stars 62 forks source link

feat request: SerializeAs Support IValueConverter #199

Open zh3305 opened 1 year ago

zh3305 commented 1 year ago

hello I'm trying to use this package to interface with Sick Lidars. I'm trying to read int data in a hexadecimal ASCII string

sourse

EA1 ED7 F13 F25 F26 EBC E82 E60 E43 DD9 DC3 DC4 D65 14B3 BBD BA5 14B1 1470 14B1 14AA 14B1 14B0 14B2 14B7 14B3 14B5 14B6 14BC 14C3 14C4 14C6 14C7 14C7 14CD 14D1 14D6 14D8 14E0 14E6 14E0 14E3 14E7 14F2 14F2 14F6 1501 1506 1505 150B 1513 1516 1524 1529 1538 1542 1543 154A 1554 1559 1564 1567 1579 1577 1586 158C 1599 15A1 15B0 15AB 15C2 15D2 15D4 15E0 15EC 15E3 158A 152B 14D6 1487 143A 13E4 13A4 1354 1310 12CA 1286 123F 1209 11CF 1190 1153 1123 10E6 10B4 1080 1054 1026 FF1 FC2 F95 F6B F41 F1A EEF ECC EA4 E7F E5E E35 E10 DE9 DCE DAE D8A D6B D4B D2F D0F CFC CDC CB9 CA2 C86 C70 C52 C3A C26 C0A BED BDC BC4 BAC B9B B87 B6D B5A B43 B30 B20 B0B AF9 AE8 AD2 ACF AC2 AB1 A9B A82 A6A A63 A4E A45 A34 A2B A13 A07 9FA 9EA 9DA 9D7 9C3 9B1 9AD 99F 993 983 978 969 962 953 94A 93D 937 92C 921 914 90E 903 8F3 8EE 8E9 8D8 8D3 8CD 8C3 8B6 8AE 89F 89F 89F 887 881 880 872 871 868 861 857 852 84C 844 840 83B 830 82E 829 819 817 815 80E 815 805 7FE 7FC 7FB 7EF 7EA 7E9 7E4 7DA 7D5 7D2 7CC 7CA 7C6 7C1 7BA 7C0 7B2 7B5 7A9 7A6 7B1 7A2 79C 798 798 790 78C 790 787 78B 78C 781 782 781 780 77A 778 770 771 76F 769 765 769 765 765 763 75F 758 75C 75C 758 755 756 759 75B 752 754 751 750 750 750 750 750 74E 74F 74A 743 74C 744 74A 74B 73F 745 746 748 748 74A 74B 748 74D 74A 74C 747 74A 74F 74B 744 74A 754 750 74F 74E 751 751 755 754 75C 759 760 762 763 761 75C 76A 766 766 768 766 76F 76F 778 774 778 77A 777 77B 785 784 789 788 78D 792 78D 790 79D 7A1 7A0 7AE 7A5 7AB 7B1 7B3 7BB 7C0 7C1 7C9 7C9 7CB 7CA 7D6 7D7 7DE 7E5 7F0 7F6 7FC 7FC 80A 804 808 80E 818 820 826 82C 830 834 83A 84B 84F 848 85B 862 86D 876 875 884 87F 88E 898 89B 8A6 8A9 8B4 8BB 8BD 8DB 8DB 8DC 8E7 8F3 8FF 909 912 91B 91F 92E 939 947 957 95B 967 96F 97C 989 992 9A7 9AE 9B8 9C5 9D0 9E6 9EE 9FC A10 A1E A27 A32 A46 A54 A65 A7A A83 A93 AA9 AB9 AC1 AD8 AE6 AFA B0F B24 B3A B4A B59 B6F B87 B9D BAF BCC BDF BF5 C0E C25 C38 C56 C69 C88 CA5 CC0 CD4 CF9 D15 D2D D4F D72 D88 DA3 DC6 0 0 0 0 0 0 0 0 0 0 E1E E1B E14 E00 E01 DEF E0C E30 E36 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1A7 1A4 1A1 1A6 1A5 1A5 1A9 1A6 1A3 1AB 1A6 1A4 1A5 19D 1A2 19D 19F 1A5 1A1 19D 19E 1A0 198 1A0 19B 198 19C 19B 194 199 196 196 194 19C 195 193 198 196 195 198 19B 197 194 196 197 195 192 194 191 197 192 193 19A 199 194 196 194 19B 199

Normal running code:

public class OutputChannel
{
        [FieldOrder(0)]
        [SerializeAs(SerializedType.TerminatedString, StringTerminator = (char)0x20)]
        public string DataAmount { get; set; }

        //数据列表
        [FieldOrder(1)]
        [FieldCount(nameof(DataAmount), ConverterType = typeof(StringLengtConvert))]
        public List<DistData> DistDatas{ get; set; }
}
public class DistData
  {
      [SerializeAs(SerializedType.TerminatedString, StringTerminator = (char)0x20)]
      public string Data { get; set; }
  }
 class StringLengtConvert : IValueConverter
    {
        // Read
        public object Convert(object value, object parameter, BinarySerializationContext context)
        {
            return (System.Convert.ToInt32((string)value,16) + System.Convert.ToInt32(parameter));
        }
        //Write
        public object ConvertBack(object value, object parameter, BinarySerializationContext context)
        {
            return (System.Convert.ToInt32(value) - System.Convert.ToInt32(parameter));
        }
    }

I want to change string to int:

public class DistData
  {
      [SerializeAs(SerializedType.TerminatedString, StringTerminator = (char)0x20, ConverterType = typeof(StringLengtConvert))]
      public int Data { get; set; }
  }

I looked at BinarySerialization.Graph.ValueGraph class's method Deserialize, when the code ConvertToFieldType (value). IValueConverter or Convet Format is not supported

127

76

jefffhaynes commented 1 year ago

Can you convert the hex to binary first? I think it would be easier to process then.

zh3305 commented 1 year ago

Can you convert the hex to binary first? I think it would be easier to process then.

I have created a small test

I want to change DataAmount,DistData.Data to int type

    [TestClass]
    public class Issue199Tests : TestBase
    {
        BinarySerializer serializer = new BinarySerializer();
        [TestMethod]
        public void Test()
        {

            var testdata = "A ED7 F13 F25 F26 EBC E82 E60 E43 DD9 DC3 DC4 ";
            var stringToByte = StringToByte(testdata);

            var outputChannel = serializer.Deserialize<OutputChannel>(stringToByte);

            // TestContext.Out.WriteLine(JsonConvert.SerializeObject(outputChannel));

            Assert.AreEqual(Convert.ToInt32(outputChannel.DataAmount, 16), outputChannel.DistDatas.Count);
            Assert.AreEqual(Convert.ToInt32("ED7", 16), Convert.ToInt32(outputChannel.DistDatas[0].Data, 16));
        }
 public static byte[] StringToByte(string str)
        {
            byte[] bytes = new byte[str.Length];
            for (int i = 0; i < str.Length; i++)
            {
                bytes[i] = (byte)str[i];
            }

            return bytes;
        }

       public class OutputChannel
{
    [FieldOrder(0)]
    [SerializeAs(SerializedType.TerminatedString, StringTerminator = (char)0x20)]
    public string DataAmount { get; set; }

    //数据列表
    [FieldOrder(1)]
    [FieldCount(nameof(DataAmount), ConverterType = typeof(StringLengtConvert))]
    public List<DistData> DistDatas { get; set; }
}

public class DistData
{
    [SerializeAs(SerializedType.TerminatedString, StringTerminator = (char)0x20)]
    public string Data { get; set; }
}

class StringLengtConvert : IValueConverter
{
    // Read
    public object Convert(object value, object parameter, BinarySerializationContext context)
    {
        return (System.Convert.ToInt32((string)value, 16) + System.Convert.ToInt32(parameter));
    }

    //Write
    public object ConvertBack(object value, object parameter, BinarySerializationContext context)
    {
        return (System.Convert.ToInt32(value) - System.Convert.ToInt32(parameter));
    }
}
    }