Search code examples
c#.netexpressionexpression-treesdsl

Expression parsing - Possible to get array of property names as string?


Is it possible to complete this method? Is it possible in the latest version of C#? Thinking about this as a DSL to configure a system for watching for certain property changes on certain objects.

List<string> list = GetProps<AccountOwner>(x => new object[] {x.AccountOwnerName, x.AccountOwnerNumber}); 
// would return "AccountOwnerName" and "AccountOwnerNumber"

public List<string> GetProps<T>(Expression<Func<T, object[]>> exp)
{  
    // code here
}

Solution

  • In C# 6, you'd use:

    List<string> list = new List<string>
    {
        nameof(AccountOwner.AccountOwnerName),
        nameof(AccountOwner.AccountOwnerNumber)
    };
    

    Before that, you could certainly break the expression tree apart - the easiest way of working out how is probably to either use an expression tree visualizer, or use the code you've got and put a break point in the method (just make it return null for now) and examine the expression tree in the debugger. I'm sure it won't be very complicated - just a bit more than normal due to the array.

    You could possibly simplify it using an anonymous type, if you use:

    List<string> list = Properties<AccountOwner>.GetNames(x => new {x.AccountOwnerName, x.AccountOwnerNumber});
    

    Then you could have:

    public static class Properties<TSource>
    {
        public static List<string> GetNames<TResult>(Func<TSource, TResult> ignored)
        {
            // Use normal reflection to get the properties
        }
    }
    

    If you don't care about the ordering, you could just use

    return typeof(TResult).GetProperties().Select(p => p.Name).ToList();
    

    If you do care about the ordering, you'd need to look at the names the C# compiler gives to the constructor parameters instead - it's a bit ugly. Note that we don't need an expression tree though - we only need the property names from the anonymous type. (An expression tree would work just as well, admittedly.)