Singleton объект не возвращает значение поля, которое он создал при инициализации

Рейтинг: 0Ответов: 1Опубликовано: 16.04.2023

Решил написать бота на C# Telegram.Bot. Я видел много туториалов, в котором тяжело было расширять бота. Я начал его писать как сервис, с Dependency Injection. Чтобы пользоваться одним объектом ITelegramBotClient(этот объект позволяет боту: написать сообщение, удалить участника из группы, то есть использовать его API). В program.cs добавил этот объект как Singleton. Но начали происходить ошибки. Во время дебага, увидел, что мой объект TelegramBot(который должен возращать один объект ITelegramBotClient) присваивает его readonly полю. Но когда я извне пытаюсь добраться до этого поля через свойство или метод, мне возращает null. Помогите пожалуйста:

Program.cs:

namespace WorkerService1
{
    public class Program
    {
        public static void Main(string[] args)
        {
            IHost host = Host.CreateDefaultBuilder(args)
                .ConfigureServices(services =>
                {
                    services.AddHostedService<Worker>();
                    services.AddSingleton<TelegramBot>(); // Здесь я добавил свой объект как синглтон
                    services.AddSingleton<IUpdateHandler, UpdateHandler>();
                    services.AddSingleton<ICommandExecutor, CommandExecutor>();
                    services.AddSingleton<BaseCommand, StartCommand>();
                })
                .Build();

            host.Run();
        }
    }
}

TelegramBot.cs:

namespace WorkerService1.Services
{
    public class TelegramBot
    {
        private readonly ITelegramBotClient _bot;
        private readonly IConfiguration _config;
        public TelegramBot(IConfiguration config)
        {
            _config = config;

            var token = _config.GetValue<string>("BotToken") ?? throw new Exception("There's no \"BotToken\" parameter in appsetting.json");
            var httpClientHandler = new HttpClientHandler
            {
                Proxy = new WebProxy("165.225.38.29", 10605),
                UseProxy = true
            };
            var httpClient = new HttpClient(httpClientHandler);
            var _bot = new TelegramBotClient(token, httpClient); // присваивает значение не null.
        }

        public ITelegramBotClient GetBot()
        {
            return _bot; // Однако тут возращает null
        }
    }
}

Worker.cs(этот класс отвечает за инициализацию проекта):

namespace WorkerService1
{
    public class Worker : BackgroundService
    {
        private readonly ILogger<Worker> _logger;
        private readonly IConfiguration _config;
        private readonly IUpdateHandler _updateHandler;
        private readonly TelegramBot _bot;

        public Worker(ILogger<Worker> logger, IConfiguration config, IUpdateHandler updateHandler, TelegramBot bot)
        {
            _logger = logger;
            _config = config;
            _updateHandler = updateHandler;
            _bot = bot;
        }

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            var bot = _bot.GetBot() ?? throw new Exception("TelegramBot.GetBot() has returned null value"); // Здесь всегда выбрасывает исключение.
            var receiverOptions = new ReceiverOptions
            {
                Limit = 1
            };

            bot.StartReceiving(
                updateHandler: _updateHandler,
                receiverOptions: receiverOptions,
                cancellationToken: stoppingToken
            );

            while (!stoppingToken.IsCancellationRequested) await Task.Delay(10000, stoppingToken);
        }
    }
}

Вот гит, кому нужен

https://github.com/HikashiMlbb/FannyHikashiBotTelegram/tree/master/WorkerService1

Ответы

▲ 1Принят

Когда Вы пишите:

var _bot = new TelegramBotClient(token, httpClient); 

то вы работаете не с полем класса, а с локальной переменной метода. Поэтому рабочим вариантом будет:

_bot = new TelegramBotClient(token, httpClient); 

С полями нужно работать ровно так как у Вас написано в конструкторе Worker а тут возможно вы машинально написали.