PropertyInfo.SetValue & property walking - Reflection

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

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.
 
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
 
The Font property is read-only. The Font.Bold property is read/write. I need
to set the Font.Bold, etc.
 
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.


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, BindingFlags.Instance
| BindingFlags.IgnoreCase | BindingFlags.Public);
o = pInfo.GetValue(o, null);
t = pInfo.PropertyType;
}

SetProperty(pInfo, propertyNames, propertyValue, control, o);


Mattias
 
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);
}
 
Back
Top