3

I am trying to use a generic method for foreach loop which would pass different parameter as the argument.

In this example below I would like to pass different parameters(EmployeeDisplayOrder or EmployeeEnrollOrder)

public void SaveEmployeeDisplayOrder(ICollection<Employee> employees)
{
   //some code

   foreach( var emp in employees)
   {
      UpdateSpecificEmployeeOrder(employee.id, e => e.EmployeeDisplayOrder);
   }
}

public void SaveEmployeeEnrollOrder(ICollection<Employee> employees)
{
   //some code

   foreach( var emp in employees)
   {
     UpdateSpecificEmployeeOrder(employee.id, e => e.EmployeeEnrollOrder);
   }
}

I would like to have something like this

public void UpdateEmployeeOrders(ICollection<Employee> employee)
{ 
  foreach( var emp in employees)
  {
    UpdateSpecificEmployeeOrder(employee.id, //generic property);
  }
}

and call this UpdateEmployeeOrders generic method from SaveEmployeeDisplayOrder and SaveEmployeeEnrollOrder.

Method signature for UpdateSpecificEmployeeOrder

UpdateSpecificEmployeeOrder( int employeeid, params Expression<Func<Employee, object>>[] property)

Is this possible?

Ell
  • 83
  • 1
  • 1
  • 7
  • 1
    What is the type of the 2nd parameter of `UpdateSpecificEmployeeOrder`? `string`, `int`, something else? – Scott Chamberlain Jan 08 '14 at 21:01
  • It does not appear to be a `int`, it appears to be some kind of delagate, something with the form `Func`. – Scott Chamberlain Jan 08 '14 at 21:08
  • Lets assume this is Employee class. Public class Employee { public int id; public int EmployeeDisplayOrder; public int EmployeeEnrollOrder; } – Ell Jan 08 '14 at 21:16
  • I don't care what employee looks like, I wanted to know what the `????` was in the method signature `UpdateSpecificEmployeeOrder(int id, ???? parameter)` that you have in the first two examples. Is it `Func`, `Func`, `Expression>`, or what? – Scott Chamberlain Jan 08 '14 at 21:18
  • Just provide the entire signature of `UpdateSpecificEmployeeOrder`, so that we don't need to make any assumptions about it at all. – Servy Jan 08 '14 at 21:25
  • UpdateSpecificEmployeeOrder( int employeeid, params Expression>[] property) – Ell Jan 08 '14 at 21:30
  • 1
    @Ell - code doesn't work in comments. Edit it into your question. – ChrisF Jan 08 '14 at 22:04

2 Answers2

10

Have the method accept an expression, just as the method you're passing it to does:

public class Foo
{
    public void UpdateEmployeeOrders(IEnumerable<Employee> employees,
         Expression<Func<Employee, object>> selector)
    {
        foreach (var employee in employees)
        {
            UpdateSpecificEmployeeOrder(employee.id, selector);
        }
    }
}

Also, since the only thing we ever do with employees is iterate over it, we can type the parameter as IEnumerable instead of ICollection. It provides all of the guarantees that this methods needs, while allowing a broader range of possible input types.

Servy
  • 202,030
  • 26
  • 332
  • 449
  • @ScottChamberlain Currently we have no idea what `UpdateSpecificEmployeeOrder` looks like. I made the assumption that it itself is generic, so this would work as-is. If it requires a specific type for its selector, then the same constraint would need to be added here, yes. – Servy Jan 08 '14 at 21:05
  • 1
    Since you are passing the selector which takes an `Employee` and passing it to a function with only the `id` property, how will `UpdateSpecificEmployeeOrder` have an `employee` to use the selector with? Don't you need to pass the employee instead of just the id? – Harrison Jan 08 '14 at 21:19
  • @Harrison how did `UpdateSpecificEmployeeOrder` do it in the first two code examples the OP provided? – Scott Chamberlain Jan 08 '14 at 21:21
  • @Harrison Who knows. It's what the code in the OP appears to be using though, I simply matched that. – Servy Jan 08 '14 at 21:21
  • Thank you all. It worked. I had to make sure the method signature for UpdateSpecificEmployeeOrder was same. – Ell Jan 09 '14 at 15:23
1

You have the answer in your answer... you're using lambdas... so pass a delegate in your method.

public void SaveEmployeeDisplayOrder<T>(ICollection<Employee> employees, Func<Employee, T> fetchProperty)
{
   //some code

   foreach( var employee in employees)
   {
      UpdateSpecificEmployeeOrder(employee.id, fetchProperty(employee));
   }
}

Then you would call it similar to what you had:

SaveEmployeeDisplayOrder(employees, e => e.EmployeeDisplayOrder);

or

SaveEmployeeDisplayOrder(employees, e => e.EmployeeEnrollOrder);
poy
  • 10,063
  • 9
  • 49
  • 74
  • Here it is not possible to pass e => e.EmployeeDisplayOrder as below SaveEmployeeDisplayOrder(employees, e => e.EmployeeDisplayOrder); because EmployeeDisplayOrder is a property of employee and employee is a collection. – Ell Jan 08 '14 at 21:23
  • but `e` is a single `employee` from the collection `employees` – poy Jan 08 '14 at 21:26
  • Thank you! It worked. I had to make sure the method signature for UpdateSpecificEmployeeOrder was same. – Ell Jan 09 '14 at 15:25