Tenera IT blog
  • About

Add attributes to a property at runtime.

Posted on June 22, 2011 by PeterVD Posted in Reflection, WinForms

In a project I had to create a little test application to create and edit objects of a referenced assembly. This was very early in the development stage, so the classes could possibly change a lot during the course of the project.

Instead of designing a UI for each class and getting into the process of changing it over and over again, I decided to use Reflection and the PropertyGrid control in winForms.

This worked well: getting all types via reflection, showing them in a treeview, creating an instance when the user selected a type in the treeview and showing it in the PropertyGrid. No problem there.

Even editing a property of an enumeration type was no problem.

But then I ran into a problem. Some of the enumerations were actually Flags. So the user must be able to select multiple values from the list. This is not supported by the PropertyGrid.

Fortunately there is a solution for this at CodeProject. A Flag enum editor. This can be used by the PropertyGrid control by adding an attribute to the properties that use a flag enumeration:

[Editor(typeof(FlagEnumUIEditor), typeof(System.Drawing.Design.UITypeEditor))]

Problem solved!

No wait! The items we wanted to test were defined in some business logic layer. We don’t want to add this attribute and a reference to Windows.Forms and so, to our business logic layer.

So, why can’t we just apply or set the attribute to the flag-properties at runtime?

Via reflection, using the PropertyDescriptor, you can check the attributes and get the list (or array) of attributes, but unfortunately this attribute list is readonly!

Unless you use reflection on the PropertyDescriptor as well. So, Reflection on Reflection objects. 🙂

private static readonly Attribute s_EditorAttribute = 
    new EditorAttribute(typeof(FlagEnumUIEditor), 
                        typeof(System.Drawing.Design.UITypeEditor));

/// <summary>
/// Processes the flag enum properties of the given type 
/// to set the UI-editor for property grid 
/// (Add the Editor-attribute to these properties)
/// </summary>
/// <param name="type">The type to analyse.</param>
private static void ProcessFlagProperties(Type type)
{
    var props = TypeDescriptor
        .GetProperties(type, new[] { new FlagsAttribute() });
    foreach (var prop in props)
    {
        // AttributeArray-property is not accessible 
        // => use reflection to get and set it.
        var attributeArrayPropInfo = 
            prop
            .GetType()
            .GetProperty("AttributeArray", 
                         System.Reflection.BindingFlags.Instance 
                         | System.Reflection.BindingFlags.NonPublic);
        var attributeArray = attributeArrayPropInfo
                        .GetValue(prop, null) as Attribute[];
        AddEditorAttribute(ref attributeArray);
        attributeArrayPropInfo
            .SetValue(prop, attributeArray, null);
    }
}

/// <summary>
/// Adds the editor attribute to the given attribute array.
/// </summary>
/// <param name="att">The attribute array.</param>
private static void AddEditorAttribute(ref Attribute[] att)
{
    var length = att.Length;
    if (length == 0)
    {
        att = new[] { s_EditorAttribute };
    }
    else
    {
        var newArray = new Attribute[length + 1];
        att.CopyTo(newArray, 0);
        newArray[length] = s_EditorAttribute;
        att = newArray;
    }
}

 

When I then created an instance (newObject = Activator.CreateInstance(type)) of these types, the attribute was taken into account and the checked listbox was shown in the PropertyGrid. Which was nice. 🙂

Attributes PropertyGrid Reflection WinForms
WCF Remoting »

Leave a comment Cancel reply

Your email address will not be published.

Time limit is exhausted. Please reload the CAPTCHA.

Tag cloud

Architecture Attributes Barcode Design Framework Navigational properties OO Printing PropertyGrid Reflection Remoting Serialization Silverlight WCF WinForms Work WPF

Categories

  • Architecture (3)
  • Reflection (2)
  • Silverlight (1)
  • Uncategorized (1)
  • WCF (1)
  • WinForms (1)
  • WPF (2)

Pages

  • About

Archives

  • October 2013
  • April 2013
  • April 2012
  • March 2012
  • February 2012
  • January 2012
  • June 2011

Categories

  • Architecture (3)
  • Reflection (2)
  • Silverlight (1)
  • Uncategorized (1)
  • WCF (1)
  • WinForms (1)
  • WPF (2)

WordPress

  • Log in
  • WordPress

CyberChimps WordPress Themes

© Tenera it blog