PropertyInfo.SetValue & property walking - Reflection

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.
 
M

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
 
G

Guest

The Font property is read-only. The Font.Bold property is read/write. I need
to set the Font.Bold, etc.
 
M

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.


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
 
G

Guest

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);
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top