1

Why does this work:

foreach (KeyValuePair<Main_key, Main_data> entry in mainTable.OrderBy(key=> key.Value.username)
{
    ...
}

And this doesn't:

foreach (KeyValuePair<Main_key, Main_data> entry in mainTable.OrderBy(key=> key.Value.GetType().GetProperty("username"))
{
    ...
}

Shouldn't it be the same?

Cornwell
  • 3,304
  • 7
  • 51
  • 84
  • 6
    No, `key.Value.GetType().GetProperty("username").GetValue(key.Value, null)` will be the equivalent – Sriram Sakthivel Aug 13 '14 at 19:40
  • 1
    @SriramSakthivel Your comment should be the answer with possibly a reference to http://stackoverflow.com/questions/1196991/get-property-value-from-string-using-reflection-in-c-sharp – Pete Aug 13 '14 at 19:41
  • 3
    `GetProperty` returns `PropertyInfo` not the value of the property. – L.B Aug 13 '14 at 19:42
  • @SriramSakthivel Thank you. I'm getting a "System.NullReferenceException: Object reference not set to an instance of an object." error though. Any idea why? The property does exist – Cornwell Aug 13 '14 at 19:50
  • 1
    @Cornwell [This should help](http://stackoverflow.com/questions/4660142/what-is-a-nullreferenceexception-and-how-do-i-fix-it) in case of `NullReferenceException`. Am pretty sure something is null, use debugger to inspect it. – Sriram Sakthivel Aug 13 '14 at 19:52
  • @SriramSakthivel Thank you. One last question, Could you please check my edit. GetProperties().length is returning 0. Any idea why? – Cornwell Aug 13 '14 at 20:06
  • 1
    @Cornwell your `username` is declared as field, not a property. Declare it as `public string username {get; set;}` – Sriram Sakthivel Aug 13 '14 at 20:08
  • @SriramSakthivel Thank you. I understand now. If you create an answer I will accept it – Cornwell Aug 13 '14 at 20:24

2 Answers2

2

No, GetProperty("username") returns the PropertyInfo associated with with the username property. This should be the same object for all values in your collection (assuming they are the same type). To get the value of this property for each object you'd have to call GetValue and pass in an instance of the object whose property value you'd like to return, like this:

foreach (var entry in mainTable.OrderBy(key => key.Value.GetType().GetProperty("username").GetValue(key.Value, null))
{
    ...
}

Note the use of implicit typing with the var keyword for brevity.

However, I really wouldn't do this unless you really have to; using reflection is slow compared to direct property access.

Also note, if you're trying to run this against a Linq-to-Entities provider or similar, this simply won't work. That's because the Linq provider needs to translate the expression you provide to a SQL query, and GetType, GetProperty, and GetValue simply don't have a SQL equivalent (at least not one that the Linq provider can use).


Also note, in your example, username is actually a field rather than a property. In that case, you'd use GetField("username") instead (which returns a FieldInfo):

foreach (var entry in mainTable.OrderBy(key => key.Value.GetType().GetField("username").GetValue(key.Value))
{
    ...
}

Alternatively, you could simply use dynamic, which will allow you to write something that looks like a normal property / field access, but will in fact cause the compiler to emit reflection code similar to what's described above:

foreach (var entry in mainTable.OrderBy(key => ((dynamic)key.Value).username)
{
    ...
}
p.s.w.g
  • 146,324
  • 30
  • 291
  • 331
  • Thank you. I'm getting a "System.NullReferenceException: Object reference not set to an instance of an object." error though. Any idea why? The property does exist – Cornwell Aug 13 '14 at 19:52
  • @Cornwell Is one of your values null? You might try something like `key.Value == null ? "" : key.Value.GetProperty...` – p.s.w.g Aug 13 '14 at 19:54
  • Still the same.. Please check my edit. GetProperties().length is returning 0. Any idea why? – Cornwell Aug 13 '14 at 20:05
  • @Cornwell Please see my updated answer for some alternatives. – p.s.w.g Aug 13 '14 at 21:27
2

When you call GetType().GetProperty() it returns something called PropertyInfo. It is not same as the property value. As the name suggests, it can be expanded as "Property Information".

So it returns a object which tells you many useful information about the Property like What is the type of the property, Whether it has getter/setter, Which class it lives in and so forth.

Since PropertyInfo object just gives the general information about the property it can't be the value of your property, To get your property value you need to call PropertyInfo.GetValue method.

So equivalent code for reading the property value would be:

type.GetProperty("YourPropertyName").GetValue(yourInstance, null);
Sriram Sakthivel
  • 72,067
  • 7
  • 111
  • 189