lundi 30 juillet 2018

How to normalize deserialization of array and non array types in c# and reflection?

I am currently working on a project in which a byte stream of data is to be mapped to properties of an input class. The deserialization code below does its job, but i am not happy with the DeserializeArray() - method. Is there a better and cleaner way to treat array and non array types in a similar way with Reflection.

    protected virtual void DoDeserialize(Type aType, object aInstance, PlcBinaryReader aReader)
    {
        foreach (PropertyInfo p in aType.GetProperties(BindingFlags.Public | BindingFlags.Instance))
        {
            if (p.GetValue(aInstance, null) != null)
            {
                if (p.PropertyType.IsArray)
                    DeserializeArray(p, aInstance, aReader); // this method breaks in my eyes the code
                else
                {
                    if (p.PropertyType.IsBasicType())
                        p.SetValue(aInstance, aReader.ReadData(p.PropertyType.Name, GetStrLength(p, false)));
                    else
                        DoDeserialize(p.PropertyType, p.GetValue(aInstance, null), aReader);
                }
            }
        }
    }

    private void DeserializeArray(PropertyInfo aPropInfo, object aInstance, PlcBinaryReader aReader)
    {
        Array a = (Array)aPropInfo.GetValue(aInstance, null);
        IList arr = a;
        for (var i = 0; i < a.GetLength(0); i++)
        {
            Type t = aPropInfo.PropertyType.GetElementType();
            if (t.IsBasicType())
                arr[i] = aReader.ReadData(t.Name, GetStrLength(aPropInfo, true));
            else
                DoDeserialize(t, arr[i], aReader);
        }
    }

    private byte GetStrLength(PropertyInfo aPropInfo, bool isArray)
    {
        byte result = 0;
        Type t = isArray ? aPropInfo.PropertyType.GetElementType() : aPropInfo.PropertyType;
        if (t.Name == "String")
        {
            var attr = aPropInfo.GetCustomAttributes(typeof(AdsStringLengthAttribute), true)
                .OfType<AdsStringLengthAttribute>().SingleOrDefault();
            result = attr != null ? attr.AdsStringLength : Constants.StdAdsStringLength;
        }
        return result;
    }

tia





Aucun commentaire:

Enregistrer un commentaire