C# Reflection Tips: Data transformation using Reflection

.NET Reflection can be quite handy to transform one object to another, and specially when the target data structure varies a lot. Lets say, a “source party” has a stable Source data structure. But different clients have different requirement and expects to served with data in different format. These clients may pass their object instances in their own format and expect to be served with data in their structure. Let me make up an Example here:

Source Data Structure which is consistent and never changes.

SmartDataManagement - Microsoft Visual Studio

Client 1 wants data to be transformed/served in the following structure 

Customer
Client 2 wants data to be transformed/served in the following structure

Client
and there may be other N-number of clients with N-number of structures, on which “Source Party” has no control.


The use of .NET Attribute and .NET Reflection can produce a very powerful solution to address this kind of scenario. So instead of writing different transforms for different clients, “source party” can simply ask clients to mark their class properties with custom attributes that the “source party” can understand. When clients mark their classes with custom attributes the  “source party” can easily take advantage of .NET Reflection to analyze those objects runtime and can act accordingly.

A .NET Attribute class can be designed to keep track of of the Mapping between the source and target data structure.

attribute

The client can mark their class/properties with this custom attribute for the (target -> source) mapping.

attributeMapping

As the mapping has been performed, we can take advantage of .NET Reflection to transform/serve data in different structure ( infact any structure – considering mapping is done properly ). Lets look at the following magical piece of code.

public class TransformHelper
{
    public Source SourceObject { get; set; }
    public object GetTransformedObjectObject(object obj)
    {
        foreach (PropertyInfo property in obj.GetType().GetProperties())
        {
            FillObject(property, obj);
        }
        return obj;
    }

    private void FillObject(PropertyInfo property, object obj)
    {
        //Identify Custom attribute
        SourceMapAttribute attribute = (SourceMapAttribute)Attribute.GetCustomAttribute(property, typeof(SourceMapAttribute));
        if (attribute != null)
        {
            //Check propertyName
            /*Put your desired code and logic here.*/
            if (attribute.PropertyName != string.Empty)
            {                           
                /*Put your desired code and logic here.
                I have simply demonstrated with one attribute property,
                you can have as many as you like, and can perform any complex operation you prefer.*/

                //Get Source Object Value
                object sourceValue = GetSourceValue(attribute.PropertyName);
                if (property.CanWrite)
                {
                    //Assign source value to the mapped property
                    property.SetValue(obj, sourceValue, null);
                }
            }

            Type propertyType = property.PropertyType;
            object propertyInstance = property.GetValue(obj, null);

            if (propertyInstance == null)
            {
                //Instantiate when Property is not instantiated
                propertyInstance = Activator.CreateInstance(property.PropertyType);
                if (property.CanWrite)
                    property.SetValue(obj, propertyInstance, null);
            }

            foreach (PropertyInfo info in propertyType.GetProperties())
            {
                //recursive call
                FillObject(info, propertyInstance);
            }
        }
    }

    private object GetSourceValue(string propertyName)
    {
        if (SourceObject == null)
        {
            SourceDataProvider provider = new SourceDataProvider();
            this.SourceObject = provider.GetSource();
        }

        switch (propertyName)
        {
            case “FirstName”:
                return SourceObject.FirstName;
            case “LastName”:
                return SourceObject.LastName;
            case “ContactAddress”:
                return this.SourceObject.ContactAddress;
            case “ContactPhone”:
                return this.SourceObject.ContactPhone;
            case “ContactMobile”:
                return this.SourceObject.ContactMobile;
            case “ShippingAddress”:
                return this.SourceObject.ShippingAddress;
            case “ShippingPhone”:
                return this.SourceObject.ShippingPhone;
            case “ShippingMobile”:
                return this.SourceObject.ShippingMobile;
            default:
                return string.Empty;
        }
    }
}

Its worth talking a little bit about the above code snippet, all it does is takes an instance of the target class, uses reflection to loop through all its properties, while doing that identifies the custom attributes, checks for the mapping property and assigns values from the Source. This also creates property instances as required and recursively keeps working until all the properties ( including all descendents ) are checked and served.

Lets look at this Transformer in action.

Serve Client 1:

Client1

Here is what we see after transformation.

serveclient 1


Serve Client 2:

client2
and here is the result.

serveclient2

 


In this way we can serve any clients objects in any structure ( considering, mapping is done properly ). You will sure agree with me Transforming one object to another by taking advantage of .NET Attribute and .NET Reflection is quite cool. Thank you for being with me so far, Happy coding :)

Leave a Reply

Your email address will not be published. Required fields are marked *


*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>