Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# Pass parameter to method using lambda expression

Tags:

c#

.net-core

Anyone that used ASP.Net might have seen methods that accept an Action<T> delegate that is used to configure some options. Take this one as an example in a ASP.Net Core MVC Startup.cs.

public void ConfigureServices(IServiceCollection services)
{
    services.AddAuthentication().AddJwtBearer(options => {
        options.Audience = "something";
        // ...
    });

    //...
}

The .AddJwtBearer() method takes an Action<T> delegate with the configured parameters inside the lambda expression, what I'm trying to do is replicate that in one of my projects, but with no luck. I got the Method(Action<T> action) part down, but I can't seem to retrieve the resulting object that was configured when the method was called.

Some code for context:

The builder class method:

public ReporterBuilder SetEmail(Action<EmailConfig> config)
{
    if (config is null)
        throw new ArgumentNullException();

    // Get configured EmailConfig somehow...

    return this;
}

The EmailConfig model:

public class EmailConfig
{
    public EmailProvider EmailProvider { get; set; }
    public string Host { get; set; }
    public int Port { get; set; }
    public string Username { get; set; }
    public string Password { get; set; }
    public string FromAddress { get; set; }
    public string ToAddress { get; set; }
}

So what I'm trying to achieve here is this:

Reporter reporter = new ReporterBuilder()
    .SetEmail(config => {
        config.EmailProvider = EmailProvider.Other;
        config.Host = "something";
        // ...
    })
    .Build();

I looked at some Microsoft repositories on GitHub (aspnet/DependencyInjection, aspnet/Options seen to be the two main ones that use this approach with their IoC container) to see how they do to grab values from an Action<T> delegate, with absolutely no luck.

A few hours search on the internets didn't help either, as most articles are outdated or had nothing to do with what I'm trying to do.

Any help on how I can make this work is very welcome, also suggestions on better ways this can be done are also welcome.

like image 542
Cristian Moraru Avatar asked Jun 26 '26 11:06

Cristian Moraru


1 Answers

Your method needs to instantiate the object, then call the method, passing the object into the method. A Func<T> would return an object. This is ActionT<T>, which doesn't return anything. Instead, it accepts the object.

public ReporterBuilder SetEmail(Action<EmailConfig> config)
{
    if (config == null)
        throw new ArgumentNullException();

    var cfg = new EmailConfig();

    // optionally populate the cfg with 
    // default configuration before calling method

    config(cfg);

    // cfg contains your configuration 
    // and is full of that thing called 'love'

    return this;
}