0
\$\begingroup\$

I have the requirement to return the result of my ViewModel as a Dictionary of KeyValue pairs. My view model comprises of multiple classes and can have null values in properties. I need to return only values which are not null and non-zero in case of double/string types. Following is the class I created:

public static class ObjectExtensions
    {
        public static IDictionary<string, dynamic> ConvertToDictionary(this object source, BindingFlags bindingAttribute = BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.Public)
        {
            IDictionary<string, dynamic> dictionary = new Dictionary<string, dynamic>();

            PropertyInfo[] properties = source.GetType().GetProperties(bindingAttribute);
            foreach (PropertyInfo propertyInfo in properties)
            {
                if (propertyInfo.PropertyType == typeof(System.String) ||
                    propertyInfo.PropertyType == typeof(System.Int16) ||
                    propertyInfo.PropertyType == typeof(System.Int32) ||
                    propertyInfo.PropertyType == typeof(System.Int64) ||
                    propertyInfo.PropertyType == typeof(System.Double) ||
                    propertyInfo.PropertyType == typeof(System.Decimal) ||
                    propertyInfo.PropertyType == typeof(System.Guid)
                )
                {
                    dynamic propertyValue = propertyInfo.GetValue(source, null);
                    if (propertyValue != null)
                    {
                        if (propertyValue.GetType() == typeof(double))
                        {
                            propertyValue = Math.Round(propertyValue, 4);
                        }

                        dictionary.Add(propertyInfo.Name, propertyValue);
                    }
                }
                else if (propertyInfo.PropertyType.IsGenericType)
                {
                    dynamic propertyValue = propertyInfo.GetValue(source, null);
                    if (propertyValue != null)
                    {
                        if (propertyValue.GetType() == typeof(double))
                        {
                            propertyValue = Math.Round(propertyValue, 4);
                        }

                        dictionary.Add(propertyInfo.Name, propertyValue);
                    }
                }
                else
                {
                    dynamic complexPropertyValue = propertyInfo.GetValue(source, null);
                    if (complexPropertyValue != null)
                    {
                        PropertyInfo[] complexProperties = complexPropertyValue.GetType().GetProperties();
                        foreach (PropertyInfo complexPropertyInfo in complexProperties)
                        {
                            dynamic propertyValue = complexPropertyInfo.GetValue(complexPropertyValue, null);
                            if (propertyValue != null)
                            {
                                if (propertyValue.GetType() == typeof(double))
                                {
                                    propertyValue = Math.Round(propertyValue, 4);
                                }

                                dictionary.Add(complexPropertyInfo.Name, propertyValue);
                            }
                        }
                    }
                }
            }

            FormatDictionary(dictionary);
            return dictionary;
        }

        private static IDictionary<string, dynamic> FormatDictionary(IDictionary<string, dynamic> source)
        {
            foreach (var item in source)
            {
                if (item.Value.GetType() == typeof(int) || item.Value.GetType() == typeof(double))
                {
                    if (item.Value == 0)
                    {
                        source.Remove(item);
                    }
                }

                if (item.Value.GetType() == typeof(string))
                {
                    if (string.IsNullOrWhiteSpace(item.Value))
                    {
                        source.Remove(item);
                    }
                }
            }
            return source;
        }
    }

Is it the right approach. Any feedback will be appreciated.

\$\endgroup\$
2
  • \$\begingroup\$ Right approach compared to ? \$\endgroup\$
    – Dbuggy
    Dec 6, 2019 at 7:36
  • \$\begingroup\$ For using two foreach loops to check for nested properties. \$\endgroup\$ Dec 6, 2019 at 7:38

1 Answer 1

3
\$\begingroup\$

Here is my feedback

  1. Why do you use full types name, like System.Double ? I prefer shorter version , just double.

  2. Also I prefer to use var as it makes code shorter and more readable. So instead of IDictionary<string, dynamic> dictionary = new Dictionary<string, dynamic>(); I would use var dictionary = new Dictionary<string, dynamic>(); which looks neater for me.

  3. For some reason you do not handle float datatype ... Probaly you just missed it. The same for char and boolean datatypes. So your code will fail for class with these properties types.

  4. That is also strange that you Round only double values. What about float and decimal types ? probably you should be consistent.

  5. Looks like in first if statement you wanted to check if type is built-in primitive type. I would recommend extract separate method for it - IsPrimitiveType(Type type)

  6. Function name FormatDictionary is misleading as for me. Because it does not format a dictionary, but filter it. So, I think FilterDictionary is a better name

  7. It is considered as bad practice to modify input parameter inside function, but FormatDictionary does it. I would recommend to create new collection and return it, instead of modifying existed one

That is what I see on the first glance. Probably there is something else if look closer :)

\$\endgroup\$
2

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.