Action <T> usage as parameter
Asked Answered
A

2

15

I just started with .net core and found Action<T> used everywhere. I have provide sample code from Swagger code block below. My question is what is the use of using Action<T> here? I need to pass config data. How does Swagger extract that configuration data?

 services.AddSwaggerGen(c =>
        {
            c.SwaggerDoc("v1", new Info
            {
                Version = "v1",
                Title = "My API",
                Description = "My First ASP.NET Core Web API",
                TermsOfService = "None",
                Contact = new Contact() { Name = "Talking Dotnet", Email = "[email protected]", Url = "www.x.com" }
            });
        });5
Aspirant answered 6/7, 2018 at 20:9 Comment(0)
T
22

It's a lambda function which does not return anything. You could supply a void returning method there.

Here it's just used so that you can supply a function that does something with T. It means the library can create a default options object and give you a way of modifying it.

The method would be doing something like

public void AddFoo(Action<FooOptions> configure) {
    // Create a default configuration object
    var options = new FooOptions();

    // Let the action modify it
    configure(options);

    // Do something with the now configured options
}
Testaceous answered 6/7, 2018 at 20:14 Comment(4)
Thanks George, this really helped building extension methods for IServiceCollection.Chordophone
I think this might be an old dog trying to learn a new trick kind of thing, but I'm struggling to identify why this pattern is superior to simply having the function be declared as public void AddFoo(FooOptions configurationOptions)Giraud
@ErikWestwig you're passing in a function that will load the options, rather than passing in options that have already been loaded. This allows the configuration to change over time if needed, while not having to know how it is loaded. It also guarantees that it isn't null by using a default object and then allowing it to be modified, but not deleted. It's common to use this pattern with Microsoft.Extensions.Configuration and Microsoft.Extensions.Options.Testaceous
@GeorgeHelyar I guess the idea that the options object is "owned" by the parent class has a fair amount of appeal. No need to worry about side-effects of copying things, or having someone accidentally else Dispose an object out from under you.Giraud
S
8

When you see a variable or a parameter of type Action, that means it is a reference to a method call. For example:

//Declare a method with no parameters 
void ShowMessage()
{
   Console.WriteLine("Hello world");
}

//Store a reference to that method in x
Action x = ShowMessage;

//Call that method
x();   //Displays "hello world"

Using a lambda expression, you can also define the method body inline, like this:

//Declare a lambda expression and store a reference to it in x
Action x = () => Console.WriteLine("Hello world");

//Call that method
x();   //Displays "hello world"

Now what if you need to store a reference to a method that takes parameters? Well, Action<T> is generic, meaning that various kinds of Action<T> can take parameters of different types. For example, an Action<string> can accept a string parameter.

void ShowMessage(string message)
{
    Console.WriteLine(message);
}

Action<string> x = ShowMessage;
x("Hello world");  //Displays "Hello world"

Or as a Lambda:

Action<string> x = message => Console.WriteLine(message);
x("Hello world");  //Displays "Hello world"

When a method accepts an action as an argument, is is typically going to be used as a callback. For example, LINQ's Where method accepts a delegate that is executed for each item in a list and uses its output to determine whether the item should be included in the results.

With AddSwaggerGen you are providing a reference to a method that Swashbuckle will call at some point. I believe the method in this case is supposed to generate Swagger (typically using SwaggerDoc).

Selima answered 6/7, 2018 at 20:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.