Reputation: 25
I think I'm very close to have this figured out, but I haven't made progress for some time now and don't really have a choice but to ask around.
I have a GraphicsSettings
class with a large set of graphics properties. These properties have a placeholder value with the property's name, which I use for a comparison loop.
The comparison loop is a function inside the class, and is between an array of the graphics properties and a Stringreader
going over lines in an external text file.
When the loop finds a match between the value of a graphics property and a part of what is in a line, I want to set the entire value of the line into the graphics property.
Here's the problem though, I do not know how to call the property setter from within the class without specifically typing out it's name, which I cannot do since its a loop.
I've tried using:
this.GetType().GetProperty(key).SetValue(this,line, null);
Where "key" is the property name and "line" is the line value. From what I understand, this should work just fine when calling a class object from the outside to set a value, but it seems to be utterly against calling a class from the inside using this method.
All I get is a
TargetInvocationException was unhandled
error. Not too surprising, but I dont know how to get around this.
So I guess it comes down to this: How do I access a property through the use of a string, from inside the same class where the property resides?
Upvotes: 2
Views: 719
Reputation: 112259
If the properties are not public, you might need to use binding flags, because the GetProperty
method does not know, that you are calling it from within the target class. C#'s accessibility rules apply to the static code text and do not apply here.
PropertyInfo prop = this.GetType().GetProperty(key, BindingFlags.Instance |
BindingFlags.NonPublic);
prop.SetValue(this, "data", null);
Note that finding a property is case sensitive. Therefore you also might need to include the IgnoreCase
flag.
PropertyInfo prop = this.GetType().GetProperty(key, BindingFlags.Instance |
BindingFlags.NonPublic |
BindingFlags.IgnoreCase);
prop.SetValue(this, "data", null);
If your properties were static, you would specify the BindingFlags.Static
flag instead of BindingFlags.Instance
flag. You can also combine both as well as BindingFlags.NonPublic | BindingFlags.Public
for mixed cases.
Note also that the types must match. The implicit type conversions of C# do not work here. So always provide the correct type for the value parameter (second parameter) of SetValue
. E.g.
string input = "123";
prop.SetValue(this, Int32.Parse(input), null);
int i = 77;
prop.SetValue(this, (double)i, null);
Also convert an int
to a double
explicitly, if the property is of type double
.
Chris Kerekes suggests using prop.MemberType
in conjunction with Convert.ChangeType
to get a fully dynamic approach that will work if you have properties with different types (at least for the most common types).
prop.SetValue(this, Convert.ChangeType(line, prop.MemberType), null);
Upvotes: 4