Home > Software engineering >  Initialization of Service with configure option is not passing callback delegate
Initialization of Service with configure option is not passing callback delegate

Time:05-16

I am facing issue while configuring a service with options. In method-I GreetingService constructor is receiving callbackAction while in method-II options.Value.CallBackAction is passed as null in constructor.

So calling GreetingService.Greet(string) works with Method-I while throws null exception with Method-II.

How can I pass callback delegate using Method-II

appsettings.json

{
  "GreetingService": {
    "From": "James"
  }
}

GreetingService.cs

using Microsoft.Extensions.Options;

namespace ConsoleApp
{
    public interface IGreetingService
    {
        void Greet(string name);
    }

    public class GreetingServiceOptions
    {
        public string? From { get; set; }
        public Action<string> CallBackAction { get; set; }
    }
    public class GreetingService : IGreetingService
    {
        private readonly string? _from;
        private readonly Action<string> _callBackAction;
        public GreetingService(IOptions<GreetingServiceOptions> options)
        {
            _from = options.Value.From;
            _callBackAction = options.Value.CallBackAction;
        }
        public void Greet(string name)
        {
            Console.WriteLine($"Hello, {name}! Greetings from {_from}");
            _callBackAction($"Hello, {name}! Greetings from {_from}");
        }
    }
}

program.cs

using ConsoleApp;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
//------------------------------Method-I-----------------------------------------------
//using var host = Host.CreateDefaultBuilder()
//    .ConfigureServices(services =>
//    {
//        services.Configure<GreetingServiceOptions>(options
//            =>
//        {
//            options.From = "James";
//            options.CallBackAction = delegate (string callBackmessage)
//             {
//                 Console.WriteLine(callBackmessage);
//             };
//        });
//        services.AddSingleton<IGreetingService, GreetingService>();
//    }).Build();
//---------------------------------------------------------------------------------------

//------------------------------Method-II-----------------------------------------------
using var host = Host.CreateDefaultBuilder()
    .ConfigureServices((context, services) =>
    {
        var configuration = context.Configuration;
        var options = configuration
            .GetSection("GreetingService")
            .Get<GreetingServiceOptions>();
        services.Configure<GreetingServiceOptions>(config =>
        {
            options.From = config.From;
            options.CallBackAction = delegate (string callBackmessage)
            {
                Console.WriteLine(callBackmessage);
            };
        });
        services.AddSingleton<IGreetingService, GreetingService>();
    }).Build();
//---------------------------------------------------------------------------------------
var serviceGreeting = host.Services.GetRequiredService<IGreetingService>();
serviceGreeting.Greet("Thomas");
Console.ReadLine();

CodePudding user response:

Method 2 is configuring the wrong instance

var host = Host.CreateDefaultBuilder()
.ConfigureServices((context, services) => {
    var configuration = context.Configuration;
    //Instance extracted from configuration
    GreetingServiceOptions options = configuration.GetSection("GreetingService")
        .Get<GreetingServiceOptions>();
    //configure IOptions from the extracted instance
    services.Configure<GreetingServiceOptions>(config => {
        //NOTE: the config is being modified here
        config.From = options.From;
        config.CallBackAction = delegate (string callBackmessage) {
            Console.WriteLine(callBackmessage);
        };
    });
    services.AddSingleton<IGreetingService, GreetingService>();
}).Build();

My belief here is that the confusion came out of naming of the variables.

Review following edit

var host = Host.CreateDefaultBuilder()
.ConfigureServices((context, services) => {
    IConfiguration configuration = context.Configuration;
    //Instance extracted from configuration
    GreetingServiceOptions greetingsConfig = configuration.GetSection("GreetingService")
        .Get<GreetingServiceOptions>();

    services.Configure<GreetingServiceOptions>(options => {
        options.From = greetingsConfig.From;
        options.CallBackAction = delegate (string callBackmessage) {
            Console.WriteLine(callBackmessage);
        };
    });
    services.AddSingleton<IGreetingService, GreetingService>();
}).Build();

CodePudding user response:

Your property assignment should be the other way around

services.Configure<GreetingServiceOptions>(config =>
{
    config.From = options.From;
    config.CallBackAction = delegate (string callBackmessage)
    {
        Console.WriteLine(callBackmessage);
    };
});
  • Related