Christian Sunesen
Christian Sunesen

Reputation: 25

Dynamically setting property inside own class

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

Answers (1)

Olivier Jacot-Descombes
Olivier Jacot-Descombes

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

Related Questions