Setting the value of properties via reflection I am working on an application in which I have to parse an XML file. Nodes of the XML file corresponds to an object. I have to populate the properties of the objects at run time. The code below queries the metadata of property and sets its value. Is there a better way to do it or is there a better way to map the elements of an XML to an object?

public static void SetPropertyValue(object obj, string propertyName, object propertyValue)
    {
        if (obj == null || string.IsNullOrWhiteSpace(propertyName))
        {
            return;
        }

        Type objectType = obj.GetType();

        PropertyInfo propertyDetail = GetPropertyInfo(objectType, propertyName);

        if (propertyDetail != null &amp;&amp; propertyDetail.CanWrite)
        {
            Type propertyType = propertyDetail.PropertyType;

            Type dataType = propertyType;

            // Check for nullable types
            if (propertyType.IsGenericType &amp;&amp; propertyType.GetGenericTypeDefinition() == typeof(Nullable&lt;&gt;))
            {
                // Check for null or empty string value.
                if (propertyValue == null || string.IsNullOrWhiteSpace(propertyValue.ToString()))
                {
                    propertyDetail.SetValue(obj, null);
                    return;
                }
                else
                {
                    dataType = propertyType.GetGenericArguments()[0];
                }
            }

            if (dataType.Equals(typeof(int)))
            {
                propertyValue = Convert.ToInt32(propertyValue);
            }

            if (dataType.Equals(typeof(long)))
            {
                propertyValue = Convert.ToInt64(propertyValue);
            }

            if (dataType.Equals(typeof(short)))
            {
                propertyValue = Convert.ToInt16(propertyValue);
            }

            if (dataType.Equals(typeof(bool)))
            {
                string stringPropertyValue = propertyValue.ToString();
                if (stringPropertyValue.Equals(Boolean.FalseString, StringComparison.OrdinalIgnoreCase) || stringPropertyValue.Equals("0"))
                {
                    propertyValue = false;
                }
                else
                {
                    if (stringPropertyValue.Equals(Boolean.TrueString, StringComparison.OrdinalIgnoreCase) || stringPropertyValue.Equals("1"))
                    {
                        propertyValue = true;
                    }
                }
            }

            if (dataType.Equals(typeof(float)))
            {
                propertyValue = Convert.ToSingle(propertyValue);
            }

            if (dataType.Equals(typeof(double)))
            {
                propertyValue = Convert.ToDouble(propertyValue);
            }

            if (dataType.Equals(typeof(decimal)))
            {
                propertyValue = Convert.ToDecimal(propertyValue);
            }

            if (dataType.Equals(typeof(byte)))
            {
                propertyValue = Convert.ToByte(propertyValue);
            }

            if (dataType.Equals(typeof(string)))
            {
                propertyValue = Convert.ToString(propertyValue);
            }

            if (dataType.Equals(typeof(char)))
            {
                propertyValue = Convert.ToChar(propertyValue);
            }

            if (dataType.Equals(typeof(DateTime)))
            {
                propertyValue = DateTime.ParseExact(propertyValue.ToString(), "yyyy-MM-dd", CultureInfo.InvariantCulture);
            }

            propertyDetail.SetValue(obj, propertyValue);

        }
    }
You can use reflection to parse some common .Net types:

public static object Parse(Type type, string str)
{
    try
    {
        var parse = type.GetMethod("Parse", new[] {typeof(string)});
        if (parse == null) throw new NotSupportedException();
        return parse.Invoke(null, new object[] { str });
    }
    //or don't catch
    catch (Exception)
    {
        return null;
    }
}


It will basically allow you to replace this code:

        if (dataType.Equals(typeof(float)))
        {
            propertyValue = Convert.ToSingle(propertyValue);
        }

        if (dataType.Equals(typeof(double)))
        {
            propertyValue = Convert.ToDouble(propertyValue);
        }

        if (dataType.Equals(typeof(decimal)))
        {
            propertyValue = Convert.ToDecimal(propertyValue);
        }

        if (dataType.Equals(typeof(byte)))
        {
            propertyValue = Convert.ToByte(propertyValue);
        }

        if (dataType.Equals(typeof(string)))
        {
            propertyValue = Convert.ToString(propertyValue);
        }

        if (dataType.Equals(typeof(char)))
        {
            propertyValue = Convert.ToChar(propertyValue);
        }

        if (dataType.Equals(typeof(int)))
        {
            propertyValue = Convert.ToInt32(propertyValue);
        }

        if (dataType.Equals(typeof(long)))
        {
            propertyValue = Convert.ToInt64(propertyValue);
        }

        if (dataType.Equals(typeof(short)))
        {
            propertyValue = Convert.ToInt16(propertyValue);
        }


with this line:

propertyValue = Parse(dataType, propertyValue.ToString());


It will work for every other class, that has public static void Parse(string) method declared (most standart value types do). You can add Parse(string) method to your own classes, to make them support this kind of deserialization. You can also modify the above code to use Parse(string, IFormatProvider) instead, to avoid parsing issues related to different decimal separators in different cultures.