pierre
pierre

Reputation: 1245

Use LINQ select as method parameter in C#

I am trying to create a generic method for HTML table building.

As part of the functionality I need, I'd like the user to be able to specify the properties that will be turned into columns.

As this is a generic method, I had thought that the user could pass in the properties they need as some sort of LINQ expression, and from that I would apply this select to the dataset, and loop through the properties to build the table data up:

  public static string BuildCollapsibleHtmlTable<T>(
        IEnumerable<T> dataSet,
        Func<T, object> tableDataColumnDefinitions,
        KeyValuePair<string, string>[] tableColumnNames,
        Func<T, object> groupByQuery,
        Func<T, decimal> groupSumQuery) where T : class, new() {

      ... implementation ..
   }

The 'tableColumnDefinitions' part is where I'm struggling (2nd parameter). I can get this to work for grouping and summing, but not for selecting columns/properties to use in the table:

var test = HtmlBuilders.BuildCollapsibleHtmlTable<Client>(
               Model.Clients,
               (clients => clients.ClientName),
               new KeyValuePair<string, string>[] { 
                   new KeyValuePair<string, string> ("Client", "tdCSSLeft"),
                   new KeyValuePair<string, string> ("Debt", "tdCSSCenter")
                },
               (client => client.ClientName),
               (client => client.TotalDebt)
           );

I seem only to be able to get it to work for pulling one property a time (and thus I'd need an array of expression). I'm not against this, but wondered if I'm going about this all wrong? Is there a easier/better way to pass an arbitrary select query as a parameter?

Upvotes: 1

Views: 2099

Answers (1)

xanatos
xanatos

Reputation: 111850

Yes, you'll need to use an array. Note that you seem to already have a similar array: KeyValuePair<string, string>[] tableColumnNames, so I don't see where the problem is.

Technically you could change the signature of your method in this way:

public static string BuildCollapsibleHtmlTable<T>(
    IEnumerable<T> dataSet,
    KeyValuePair<string, string>[] tableColumnNames,
    Func<T, object> groupByQuery,
    Func<T, decimal> groupSumQuery,
    params Func<T, object>[] tableDataColumnDefinitions
) where T : class, new() {

so that you wouldn't need to create an array when calling the method, but you could call it like

var test = HtmlBuilders.BuildCollapsibleHtmlTable<Client>(
           Model.Clients,
           //new KeyValuePair<string, string>[] { 
           new[] {  // Shorter
               new KeyValuePair<string, string> ("Client", "tdCSSLeft"),
               new KeyValuePair<string, string> ("Debt", "tdCSSCenter")
           },
           (client => client.ClientName),
           (client => client.TotalDebt),

           // tableDataColumnDefinitions
           (clients => clients.ClientName),
           (clients => clients.ClientSurname),
           (clients => clients.ClientAddress)
       );

Upvotes: 1

Related Questions