Search code examples
c#linqdatasetextensions

Add delegate expression as a parameter


I am trying to create a way to run some dynamic linq on a data table, the code I have pasted is test code not my full code that I am working on, but I think it is enough to get across what I am attempting to do.

Essentially I want to add a second parameter to the the method that will contain an expression that can be used to replace the r => r.Field("field").

public string GetStringValueFromData(DataTable data)
{
    switch (this.MethodType)
    {
        case (LabelMethodType.Count):
            return data.AsEnumerable().Select(r => r.Field<string>("sometextfield")).Count().ToString();
        case (LabelMethodType.Sum):
            return data.AsEnumerable().Sum(r => r.Field<decimal>("somenumberfield")).ToString();
        case (LabelMethodType.Average):
            return data.AsEnumerable().Average(r => r.Field<decimal>("anotherfield")).ToString();
    }

    return string.Empty;
}

so essentially the method would look something like this. But of course I have tried this and it does not even compile.

public string GetStringValueFromData(DataTable data, Expression<Func<DataRow, object>> expression)
{
    switch (this.MethodType)
    {
        case (LabelMethodType.Count):
            return data.AsEnumerable().Select(expression).Count().ToString();
        case (LabelMethodType.Sum):
            return data.AsEnumerable().Sum(expression).ToString();
        case (LabelMethodType.Average):
            return data.AsEnumerable().Average(expression).ToString();
    }

    return string.Empty;
}

Does anyone possibly know what type could make the parameter for this to work, so that it will accept something like r => r.Field("sometextfield") or r => r.Field("somenumberfield") or have suggestions of an alternative approach.

Thanks

CD


Solution

  • This should work as expected:

    public string GetStringValueFromData(DataTable data, Func<DataRow, object> expression)
    {
        switch (this.MethodType)
        {
            case (LabelMethodType.Count):
                return data.AsEnumerable().Select(expression).Count().ToString();
            case (LabelMethodType.Sum):
                return data.AsEnumerable().Select(expression).Cast<int>().Sum().ToString();
            case (LabelMethodType.Average):
                return data.AsEnumerable().Select(expression).Cast<int>().Average().ToString();
        }
    
        return string.Empty;
    }
    

    Notes:

    You don't need to use Expression< Func<> >, you can use just Func<>.

    The Select expression for the Count case is not necessary, the projection will never affect the count.