patterncsharpMinor
Setting the value of properties via reflection
Viewed 0 times
reflectionthepropertiesvaluesettingvia
Problem
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 && propertyDetail.CanWrite)
{
Type propertyType = propertyDetail.PropertyType;
Type dataType = propertyType;
// Check for nullable types
if (propertyType.IsGenericType && propertyType.GetGenericTypeDefinition() == typeof(Nullable<>))
{
// 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();
```
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 && propertyDetail.CanWrite)
{
Type propertyType = propertyDetail.PropertyType;
Type dataType = propertyType;
// Check for nullable types
if (propertyType.IsGenericType && propertyType.GetGenericTypeDefinition() == typeof(Nullable<>))
{
// 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();
Solution
You can use reflection to parse some common
It will basically allow you to replace this code:
with this line:
It will work for every other class, that has
.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.Code Snippets
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;
}
}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);
}propertyValue = Parse(dataType, propertyValue.ToString());Context
StackExchange Code Review Q#102289, answer score: 4
Revisions (0)
No revisions yet.