89
private void Include(IList<string> includes, Action action)
{
    if (includes != null)
    {
        foreach (var include in includes)
            action(<add include here>);
    }
}

I want to call it like that

this.Include(includes, _context.Cars.Include(<NEED TO PASS each include to here>));

The idea is pass each include to the method.

wonea
  • 4,783
  • 17
  • 86
  • 139
Jop
  • 975
  • 1
  • 7
  • 10
  • Is your `Action` just an `Action` or is it an `Action` or any other variation? How many parameters do you want? – BoltClock Feb 11 '11 at 04:05
  • It looks like you're already passing the includes via the `includes` argument. Is the idea that you want to pass each member of the `includes` list to the `action`? If so, just pass `_context.Cars.Include` (with no brackets). – itowlson Feb 11 '11 at 04:13
  • Yes the idea is to pass each include to the method _context.Cars.Include() – Jop Feb 11 '11 at 04:14
  • What error are you seeing? What is the signature of the `_context.Cars.Include` method? The Scrum Meister's updated answer looks right to me, but I guess the Cars.Include method might need adapting to take a string...? – itowlson Feb 11 '11 at 04:23
  • Getting error: 'System.Data.Objects.ObjectQuery System.Data.Objects.ObjectQuery.Include(string)' has the wrong return type. Signature is: public ObjectQuery Include(string path); – Jop Feb 11 '11 at 04:26

3 Answers3

138

If you know what parameter you want to pass, take a Action<T> for the type. Example:

void LoopMethod (Action<int> code, int count) {
     for (int i = 0; i < count; i++) {
         code(i);
     }
}

If you want the parameter to be passed to your method, make the method generic:

void LoopMethod<T> (Action<T> code, int count, T paramater) {
     for (int i = 0; i < count; i++) {
         code(paramater);
     }
}

And the caller code:

Action<string> s = Console.WriteLine;
LoopMethod(s, 10, "Hello World");

Update. Your code should look like:

private void Include(IList<string> includes, Action<string> action)
{
    if (includes != null)
    {
         foreach (var include in includes)
             action(include);
    }
}

public void test()
{
    Action<string> dg = (s) => {
        _context.Cars.Include(s);
    };
    this.Include(includes, dg);
}
The Scrum Meister
  • 29,681
  • 8
  • 66
  • 64
  • the idea is to pass each include to the method _context.Cars.Include() – Jop Feb 11 '11 at 04:16
  • With this code(code from Update) Getting error: 'System.Data.Objects.ObjectQuery System.Data.Objects.ObjectQuery.Include(string)' has the wrong return type – Jop Feb 11 '11 at 04:25
  • @jop Updated, Build a new `Action` delegate that calls the `Cars.Include`. Alternatively, your custom Include method could accept a `Func` – The Scrum Meister Feb 11 '11 at 04:30
  • Convention is that generic variant should have argument T named arg, not parameter. – magnusarinell Mar 24 '16 at 09:29
18

Dirty trick: You could as well use lambda expression to pass any code you want including the call with parameters.

this.Include(includes, () =>
{
    _context.Cars.Include(<parameters>);
});
ne2dmar
  • 504
  • 4
  • 17
  • 1
    I like this because I had a utility class already used in many places that didn't accept an `Action` - this lets me still use that without modification. – GregHNZ Aug 18 '20 at 04:20
  • 1
    This should be the accepted answer, but it's so easy. – Chris Jun 10 '21 at 19:21
  • This is what I do use, with a BlockingCollection of Action(s) to simulate what I have with C++/Qt (the signal/slot mechanism) – Aminos Sep 29 '21 at 10:33
18

You're looking for Action<T>, which takes a parameter.

SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964