Chris Strickland
Chris Strickland

Reputation: 3490

Get Excel property by name

I'm working in c# and I'm passing in chart properties as a json string, for example:

{'chart':{
'series':{
    'count':3,
    'style':'3 Series Scaled Bars',
    'data':[
        {'x':'Brand','y':'Avg Comments','type':'barScaled','position':1}
        {'x':'Brand','y':'Avg Likes','type':'barScaled','position':2}
        {'x':'Brand','y':'Avg Shares','type':'barScaled','position':3}
    ]
}}}

What I'd like to be able to do is pass in something like this: 'markerSize': 8 and be able to set the property with the string name of the property, something likes this:

Excel.SeriesCollection lines = (Excel.SeriesCollection)chrt.SeriesCollection();
Excel.Series ser = sers.Item(1);
ser.Properties("markerSize") = 8;

Is that possible, or do I have to write code to handle each property that I need to be able to modify?

Upvotes: 0

Views: 401

Answers (1)

PTwr
PTwr

Reputation: 1273

System.Reflection class may provide what you seek for.

In case some of properties will be in fact fields following code handles both situations. For COM objects it supports only properties, I am too tired to think of a way to support both fields and properties for COM objects without ugly try-catch blocks.

Why previous code failed for Interop objects? Because they are evil COM objects. While Reflection can normally return fields and properties for interface without any problem, for COM objects it failed because their true type during runtime is System._ComObject, which of course lacked properties you were looking for. Workaround is to use Invoke method, which deals with horrors of COM on its own. System._ComObject is hidden type, hence its tested as string instead of Type. (I am tired)

using System.Reflection;
...
    /// <summary>
    /// Dynamicaly sets property of given object with given value. No type casting is required. Supports COM objects properties.
    /// </summary>
    /// <param name="target">targeted object</param>
    /// <param name="propertyName">property name</param>
    /// <param name="value">desired value</param>
    /// <returns>True if success, False if failure (non existing member)</returns>
    static bool SetProperty(object target, string propertyName, object value)
    {
        Type t = target.GetType();
        if(t.ToString()=="System.__ComObject")
        {
            t.InvokeMember(propertyName, BindingFlags.SetProperty, null, target, new object[] { value });
            return true;
        }
        PropertyInfo propertyInfo = t.GetProperty(propertyName);
        FieldInfo fieldInfo = t.GetField(propertyName);
        if (propertyInfo != null)
        {
            propertyInfo.SetValue(target, Convert.ChangeType(value, propertyInfo.PropertyType, null));
            return true;
        }
        if (fieldInfo!=null)
        {
            fieldInfo.SetValue(target, Convert.ChangeType(value, fieldInfo.FieldType, null));
            return true;
        }            
        return false;
    }

//usage:
foo bar = new foo();
SetProperty(bar,"myPropertyOrField","myValue");

Upvotes: 1

Related Questions