Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to add attributes to the generated members of an ExpandoObject instance?

I'm trying to use an ExpandoObject as the SelectedObject of a PropertyGrid. I know how to add the properties I want to the ExpandoObject:

public dynamic MakePropertyObject()
{
    dynamic expando = new ExpandoObject();
    var dictionary = expando as IDictionary<string, object>;
    foreach(MyClass m in PropertiesINeedToAdd)
        dictionary[m.Name] = m.Value;
    return expando;
}

This code's working fine- the debugger shows the names and values of expando's properties as expected.

However, none of the generated properties is showing up in the PropertyGrid when I set the return value of MakePropertyObject() to its SelectedObject property. I assume (perhaps falsely) that this is because the ExpandoObject's properties don't have any DisplayNameAttribute, DescriptionAttribute, or any of the other attributes used to control how properties are displayed in a PropertyGrid.

I've done some reading and some Googling, and I can't figure out if there's a way to decorate the generated properties of an ExpandoObject with custom attributes. Does anyone know how this can be done, or of a better way to show an ExpandoObject in a PropertyGrid?

SOLUTION:

The answer provided by @Stephen Cleary was correct and helpful (thanks, Stephen). For others with the same problem, implementing ICustomTypeDescriptor worked perfectly for me.

As a side note, the object that implements ICustomTypeDescriptor provides the property and event descriptors for itself, not for another object. I thought the descriptor and the described were supposed to be linked by an attribute or something at first- it seemed confusing and redundant to me that an object should describe its own type, but that's indeed how PropertyGrids use the ICustomTypeDescriptor interface.

like image 954
Michael Hoffmann Avatar asked Apr 23 '11 20:04

Michael Hoffmann


People also ask

How do I add properties to ExpandoObject?

// Add properties dynamically to expando AddProperty(expando, "Language", "English"); The AddProperty method takes advantage of the support that ExpandoObject has for IDictionary<string, object> and allows us to add properties using values we determine at runtime.

What is an ExpandoObject in c#?

The ExpandoObject class enables you to add and delete members of its instances at run time and also to set and get values of these members. This class supports dynamic binding, which enables you to use standard syntax like sampleObject. sampleMember instead of more complex syntax like sampleObject.

How do I know if I have ExpandoObject property?

For ExpandoObject, you can simply check whether the property is defined as a key in the underlying dictionary. For other implementations, it might be challenging and sometimes the only way is to work with exceptions.


1 Answers

The problem is actually that reflection doesn't work as expected on dynamic types.

PropertyGrid uses reflection to examine its object's properties, and ExpandoObject doesn't have any (static) properties.

You can implement ICustomTypeDescriptor to "hijack" the reflection and query the (dynamic) properties of the ExpandoObject. The code for DynamicTypeDescriptorWrapper in this blog post would be a good starting point.

like image 63
Stephen Cleary Avatar answered Sep 28 '22 16:09

Stephen Cleary