Home All Groups Group Topic Archive Search About

PropertyInfo.SetValue & property walking - Reflection

Author
26 Jan 2006 8:20 PM
RR
Hi,

I'm working on a project that requires me to set some control property
values at runtime using reflection.  However, I'm not sure how to achieve
that when it's something like Font.Bold.  I need to set the Bold property of
the Font object to true or false, but not sure how to go about it.  The
property is presented to me in the form "Font-Bold", which is a string. I
then split that value and try walking the properties, but keep running into
dead ends.

--so imagine that:
string propertyName = "Font-Bold";
string propertyValue = "true";
control = new SomeWebControl();
Type controlType = control.GetType();

if (propertyName.IndexOf("-") > -1)
                {
                    // Need to walk properties (we're looking at a property like
                    // Font-Bold="true", which translates to control.Font.Bold)
                    string[] propertyNames = propertyName.Split('-');
                    int walkCounter = 1;
                    PropertyInfo pInfo = null;

                    foreach (string propertyName in propertyNames)
                    {
                        // if first time through, then get the first PropertyInfo from the
control
                        if (walkCounter == 1)
                        {
                            pInfo = controlType.GetProperty(propertyName, BindingFlags.Instance |
BindingFlags.IgnoreCase | BindingFlags.Public);
                        }
                        else // on subsequent iterations, get PropertyInfo from previous
PropertyInfo.
                        {
                            pInfo = pInfo.PropertyType.GetProperty(propertyName,
BindingFlags.Instance | BindingFlags.IgnoreCase | BindingFlags.Public);                           
                        }

                        if (pInfo == null)
                            break;



                        // if last property to walk, set property value.
                        if (walkCounter == propertyNames.Length)
                            SetProperty(pInfo, propertyName, propertyValue, control, propertyObj);

                        walkCounter++;
                    }
                }

private static void SetProperty(PropertyInfo pInfo, string propertyName,
string propertyValue, Control control, object objectToSetValue)
        {
            _log.EnterMethod();

            System.Type pType = pInfo.PropertyType;
            if (pType == typeof(string))
                pInfo.SetValue(objectToSetValue, propertyValue, null);               
            else if (pType == typeof(bool))
                pInfo.SetValue(objectToSetValue, Convert.ToBoolean(propertyValue),
null);       
            else if (pType == typeof(int))
                pInfo.SetValue(objectToSetValue, Convert.ToInt32(propertyValue), null);
                        //pInfo.SetValue(control, Convert.ChangeType(propertyValue,
pInfo.PropertyType, CultureInfo.InvariantCulture), null);
        }

It seems that I need to pass the object instance of Font, but not sure how
to get that instance from the PropertyInfo of the control in the first
place???  Any ideas would be appreciated.

Author
26 Jan 2006 8:57 PM
Mattias Sjögren
>However, I'm not sure how to achieve
>that when it's something like Font.Bold.

Font.Bold is a readonly property, so you can't set that with or
without reflection.


Mattias

--
Mattias Sjögren [C# MVP]  mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.
Author
26 Jan 2006 9:20 PM
RR
The Font property is read-only. The Font.Bold property is read/write. I need
to set the Font.Bold, etc.

Show quote
"Mattias Sjögren" wrote:

> >However, I'm not sure how to achieve
> >that when it's something like Font.Bold.
>
> Font.Bold is a readonly property, so you can't set that with or
> without reflection.
>
>
> Mattias
>
> --
> Mattias Sjögren [C# MVP]  mattias @ mvps.org
> http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
> Please reply only to the newsgroup.
>
Author
26 Jan 2006 9:45 PM
Mattias Sjögren
>The Font property is read-only. The Font.Bold property is read/write. I need
>to set the Font.Bold, etc.

Sorry I see now you're talking about web controls and the FontInfo
class. I assumed Winforms and the GDI+ Font class.


>>>It seems that I need to pass the object instance of Font, but not sure how
>>>to get that instance from the PropertyInfo of the control in the first
>>>place???

You have to call pInfo.GetValue for each level. I would probably write
it something like this

PropertyInfo pInfo = null;
object o = control;
int i = 0;
Type t = controlType;

for (; i < propertyNames.Length - 1; i++)
{
    pInfo = t.GetProperty(propertyNames[i], BindingFlags.Instance
| BindingFlags.IgnoreCase | BindingFlags.Public);
    o = pInfo.GetValue(o, null);
    t = pInfo.PropertyType;
}

SetProperty(pInfo, propertyNames[i], propertyValue, control, o);


Mattias

--
Mattias Sjögren [C# MVP]  mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.
Author
26 Jan 2006 10:15 PM
RR
Thank you Mattias.  I finally found a way and was coming here to post it and
saw your suggestion. I don't know if it works or not yet, but thought I'd
post what does work at this point.

string propertyName = "Font-Bold";
string propertyValue = "true";
control = new SomeWebControl();
Type controlType = control.GetType();

if (propertyName.IndexOf("-") > -1)
{
    // Need to walk properties (we're looking at a property like
    // Font-Bold="true", which translates to control.Font.Bold)
    string[] propertyNames = propertyName.Split('-');
    int walkCounter = 1;
    PropertyInfo pInfo = null;

    foreach (string propertyName in propertyNames)
    {
        // if first time through, then get the first PropertyInfo from the control
        if (walkCounter == 1)
        {
            propertyObj = controlType.InvokeMember(propertyName,
BindingFlags.GetProperty, null, control, null );
            pInfo = controlType.GetProperty(propertyName, BindingFlags.Instance |
BindingFlags.IgnoreCase | BindingFlags.Public);
        }
        else // on subsequent iterations, get PropertyInfo from previous
PropertyInfo.
        {
            // if not finished walking the property, then set the propertyObj again.
            if (walkCounter != propertyNames.Length)
                propertyObj = pInfo.PropertyType.InvokeMember(propertyName,
BindingFlags.GetProperty, null, propertyObj, null );

            pInfo = pInfo.PropertyType.GetProperty(propertyName,
BindingFlags.Instance | BindingFlags.IgnoreCase | BindingFlags.Public);                           
        }

        if (pInfo == null)
            break;

        // if last property to walk, set property value.
        if (walkCounter == propertyNames.Length)
            SetProperty(pInfo, propertyName, propertyValue, control, propertyObj);

        walkCounter++;
    }
}


private static void SetProperty(PropertyInfo pInfo, string propertyName,
string propertyValue, Control control, object objectToSetValue)
{       
    System.Type pType = pInfo.PropertyType;

    if (pType == typeof(string))
        pInfo.SetValue(objectToSetValue, propertyValue, null);               
    else if (pType == typeof(bool))
        pInfo.SetValue(objectToSetValue, Convert.ToBoolean(propertyValue), null);       
    else if (pType == typeof(int))
        pInfo.SetValue(objectToSetValue, Convert.ToInt32(propertyValue), null);
}

AddThis Social Bookmark Button