9

I'm trying to write a linq query that takes a dynamic property name. So for example, if the property name is 'test', a simple query would look like this:

var test = testList.Select(x => x.test).Distinct().ToList();

But I want to dynamically generate the property name, eg:

var propertyName = "test";

var test = testList.Select(x => x.propertyName).Distinct().ToList();

I get an error because 'propertyName' isn't an actual property.

What would be the best way to achieve this?

Leandro Bardelli
  • 10,561
  • 15
  • 79
  • 116
richard
  • 93
  • 1
  • 5
  • 3
    You can't do that. If `testList` is full of `ExpandoObjects` (not recommended), you could cast them to `IDictionary` and index with a string. You could also use reflection (not recommended all that highly either). But it's unlikely that you really need to do any of this. What problem are you using this LINQ query to solve? – 15ee8f99-57ff-4f92-890c-b56153 Mar 22 '17 at 16:52
  • ...oh, also you could build a property selector lambda with `Expression>` or whatever. I don't know offhand how recommended that is, probably more than the others. – 15ee8f99-57ff-4f92-890c-b56153 Mar 22 '17 at 16:56
  • 1
    Thanks for the replies, I'm probably going about this the wrong way. I'm just trying to extract a list of unique values of a property similar to this - http://stackoverflow.com/questions/10255121/get-a-list-of-distinct-values-in-list but there are several properties and classes I need to do this for. I wanted to dynamically generate the property name to avoid having to duplicate the code. – richard Mar 22 '17 at 17:31
  • Well, that's a case where it's worth considering. You know what, a somewhat glorified version of itsme386's reflection code is probably best. I'd write a for the lambda that looks for the property and if it's missing, raises a more specific and informative exception than NullReference. – 15ee8f99-57ff-4f92-890c-b56153 Mar 22 '17 at 17:40

1 Answers1

20

You'd have to use reflection to do what you're trying to do:

var test = testList
               .Select(x => x.GetType().GetProperty(propertyName).GetValue(x))
               .Distinct()
               .ToList();
itsme86
  • 19,266
  • 4
  • 41
  • 57
  • 3
    Of course you lose all type checking with this so it's prone to nasty errors. – DavidG Mar 22 '17 at 16:58
  • Also, this isn't the same thing, it returns an enumeration of `object` whereas the original code is type specific. – DavidG Mar 22 '17 at 16:59
  • @DavidG That's a good point. I guess if you knew the return type of all the properties you'd ever use this expression for, you could add a `.Cast()` before `.Distinct()` or just cast the object `GetValue()` returns. Building an expression like @EdPlunkett suggested is probably more type safe. – itsme86 Mar 22 '17 at 17:02
  • 1
    Brilliant! that works, I just added `.Cast()` as you said which is fine for what I need it to do. – richard Mar 22 '17 at 18:05