The answers given here work when either a single property is selected, or when several properties are selected. None of them work for both. Lukazoid's answer only works for a few properties, the rest is for a single property, starting with writing my answer.
The code below is considered as a case, i.e. You can use it to select one property and several properties. Please note that I have not added any checks, so feel free to add your own.
string[] Foo<T>(Expression<Func<Person, T>> func) { if (func.Body is NewExpression) { // expression selects multiple properties, // OR, single property but as an anonymous object // extract property names right from the expression itself return (func.Body as NewExpression).Members.Select(m => m.Name).ToArray(); // Or, simply using reflection, as shown by Lukazoid // return typeof(T).GetProperties().Select(p => p.Name).ToArray(); } else { // expression selects only a single property of Person, // and not as an anonymous object. return new string[] { (func.Body as MemberExpression).Member.Name }; } }
Or more concisely, using the ternary operator, all this becomes the following:
string[] Foo<T>(Expression<Func<Person, T>> func) { return (func.Body as NewExpression) != null ? typeof(T).GetProperties().Select(p => p.Name).ToArray() : new string[] { (func.Body as MemberExpression).Member.Name }; }
Download LinkPad File: LinkPad
Watch it online: Repl.it
Please feel free to point out what I may have missed.
source share