Using Reflection to set web part properties

Think about this scenario: you are tasked to do develop a custom SharePoint web part with a few custom properties. This custom web part will be removed and added back to a page during feature activation during a typical solution patch deployment process.
The requirement dictates that web part properties are preserved instead of being reset to their default value after this patch is deployed.

I tried to make a general solution to this by not worrying about the Type of the web part of which the properties we want to preserve. This makes use of Reflection in order to retrieve and set the web part properties. When I implement my web parts, I typically group custom properties in category groups by decorating the property with System.ComponentModel.CategoryAttribute attribute.

For example:

[System.Web.UI.WebControls.WebParts.WebBrowsable(true),
System.ComponentModel.Category("Parameters"),
Microsoft.SharePoint.WebPartPages.FriendlyName("Header Text"),
System.Web.UI.WebControls.WebParts.Personalizable(System.Web.UI.WebControls.WebParts.PersonalizationScope.Shared),
System.Web.UI.WebControls.WebParts.WebDisplayName("Header Text"),
System.Web.UI.WebControls.WebParts.WebDescription("Header text for the grid")]
public string HeaderText { get; set; }

Right before you remove the old web part, use the following method to collect properties using reflection:

private Dictionary<string, object> CollectExistingProperties(System.Web.UI.WebControls.WebParts.WebPart existingWp)
{
    Dictionary<string, object> existingProperties = new Dictionary<string, object>();
    PropertyInfo[] properties = existingWp.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
    if (properties == null) return existingProperties;
    foreach (PropertyInfo prop in properties)
    {
        object[] myAttributes = prop.GetCustomAttributes(typeof(System.ComponentModel.CategoryAttribute), true);
        if (myAttributes != null && myAttributes.Length > 0)
        {
            for (int j = 0; j < myAttributes.Length; j++)
            {
                if (string.Compare(((System.ComponentModel.CategoryAttribute)myAttributes[j]).Category, "Parameters", true) == 0)
                {
                    existingProperties.Add(prop.Name, prop.GetValue(existingWp, null));
                }
            }
        }
    }
    return existingProperties;
}

Then, for the new web part, use the following method to set custom properties which have been ‘preserved’ earlier:

private void SetPropertyCollection(ref System.Web.UI.WebControls.WebParts.WebPart webPart, Dictionary<string, object> preserved)
{
    PropertyInfo[] runtimeProperties = webPart.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
    if (preserved != null && preserved.Count > 0 && runtimeProperties == null)
    {
        //Handle error
    }

    foreach (PropertyInfo prop in runtimeProperties)
    {
        object[] myAttributes = prop.GetCustomAttributes(typeof(System.ComponentModel.CategoryAttribute), true);
        if (myAttributes != null && myAttributes.Length > 0)
        {
            for (int j = 0; j < myAttributes.Length; j++)
            {
                if (string.Compare(((System.ComponentModel.CategoryAttribute)myAttributes[j]).Category, "Parameters", true) == 0)
                {
                    if (preserved.ContainsKey(prop.Name))
                    {
                        prop.SetValue(webPart, preserved[prop.Name], null);
                    }
                }
            }
        }
    }
}
Advertisements

Posted on November 1, 2011, in Sharepoint and tagged , , , . Bookmark the permalink. 1 Comment.

  1. Very clever, I was casting the WebParts WebBrowsableObject – I prefer this method as there is no need for a reference.

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

%d bloggers like this: