Filling model properties using Reflection

In this topic I’m going to show how to fill object properties using reflection no matter what types they are.

Let’s take some example. Say, we have some input CSV file with header and values:

Manufacturer;Model;Color;OS;ReleaseDate;Rating
HTC;Titan;Black;Windows Phone 7.5;20111007;10.0
Samsung;Galaxy S3;White;Android 4.0.4;20120529;9.8
Nokia; Lumia 920;Yellow;Windows Phone 8;20121102;9.9

We are going to operate with these values in our application. First of all we need to parse each line. It can be done manually or using some existing library. Parsed values we can store in a dictionary, for instance. Anyway, it’s not a question of the topic.

So, we have parsed values and it would be more convenient to have a filled model with corresponding properties. Let’s declare it:

using System;
using System.Drawing;

public class Device
{
    public string Manufacturer { get; set; }
    public string Model { get; set; }
    public Color Color { get; set; }
    public string OS { get; set; }
    public DateTime ReleaseDate { get; set; }
    public float Rating { get; set; }
}

As input data we have dictionary (key is a property name). We need to write code that accepts model type and input data. And then it should create, fill and return model instance. Note, that all input values are strings. We need to convert them to the appropriate type. And release date has a custom format in this example, so we need to handle it separately.

Using Reflection we can easily access each property: get it’s type, get or set value, get the type’s converter to parse string and create value. So, here is the code that does magic :)

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Reflection;

public static T CreateModel<T>(IDictionary<string, string> inputValues)
    where T : new()
{
    // Get the properties that should be filled. Take only public properties from
    // the current type (without properties from the base classes).
    var properties = typeof(T).GetProperties(
        BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);

    // Create model.
    var model = new T();

    // Fill each property of the model.
    foreach (var property in properties)
    {
        // Get the string value from the input data dictionary.
        var stringValue = inputValues[property.Name];

        // Get the type of property that should be filled with value converted from string value.
        var type = property.PropertyType;

        // The input string can be null or empty.
        if (string.IsNullOrEmpty(stringValue))
        {
            // In this case we skip property so it will have default value for it's type.
            continue;
        }

        // Create the value for the property.
        object value;

        // Convert DateTime separately because it has custom format in our example.
        // Otherwise we don't need this part of code.
        if (type == typeof(DateTime))
        {
            // Format is hardcoded here but it can be retrieved from the attribute
            // attached to the property.
            value = DateTime.ParseExact(stringValue, "yyyyMMdd", CultureInfo.InvariantCulture);
        }
        else
        {
            // Need to convert string value to the type of property.
            // First, we need to find convertered for the type.
            var converter = TypeDescriptor.GetConverter(type);

            // Second, we use converter for converting string into value.
            value = converter.ConvertFromString(stringValue);
        }

        // Set the property value.
        property.SetValue(model, value, null);
    }

    return model;
}

And small demo:

var dictinary = new Dictionary<string, string>
                {
                    { "Manufacturer", "HTC" },
                    { "Model", "Titan" },
                    { "Color", "Black" },
                    { "OS", "Windows Phone 7.5" },
                    { "ReleaseDate", "20111007" },
                    { "Rating", "10.0" },
                };

var device = CreateModel<Device>(dictinary);

It’s quite easy, isn’t it?

One thought on “Filling model properties using Reflection

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s