@D8i

Как получать реализации интерфеса из ServiceProvider?

Здравствуйте. Несколько суток не дает нормально жить одна проблема.
Есть .net core приложение, использую в нем Microsoft.Extensions.DependencyInjection. Хотел реализовать так называемый CommandHandler, который по строке ищет нужный класс и исполняет метод Execute.
Класс такой:
[Command("time")]
    public class TimeCommand : ICommand
    {
        private readonly IVkApi _vkApi;

        public TimeCommand(IVkApi vkApi)
        {
            _vkApi = vkApi;
        }

        public void Execute(Message message)
        {
            _vkApi.Messages.Send(new MessagesSendParams
            {
                RandomId = DateTime.Now.Millisecond,
                PeerId = message.PeerId,
                Message = DateTime.Now.ToString(CultureInfo.InvariantCulture)
            });
        }
    }


Как мне сделать сделать, чтобы в ServiceProvider добавились автоматически все реализации интерфейса ICommand и как мне их потом получить в другом классе? Либо это вообще делается как-то иначе?

Сейчас имею такой код:
Метод ConfigureServices:
private static ServiceProvider ConfigureServices()
        {
            var services = new ServiceCollection()
                .AddLogging(builder => builder.AddConsole()).AddTransient(typeof(VkLongPollService))
                .AddSingleton<IConfiguration>(provider =>
                {
                    var confBuilder = new ConfigurationBuilder()
                        .SetBasePath(Directory.GetCurrentDirectory())
                        .AddJsonFile("Configuration/Settings.json");
                    return confBuilder.Build();
                })
                .AddSingleton<IVkApi>(provider =>
                {
                    var vkApi = new VkApi();
                    vkApi.Authorize(new ApiAuthParams
                    {
                        AccessToken = provider.GetRequiredService<IConfiguration>()["VkAccessToken"]
                    });
                    return vkApi;
                })
                .AddSingleton<VkLongPollService>();

            services.AddSingleton<ICommand, TimeCommand>();

            services.AddSingleton<CommandHandlingService>();

            return services.BuildServiceProvider();
        }
    }


Класс CommandHandlingService:
public class CommandHandlingService
    {
        private readonly IServiceProvider _provider;

        public CommandHandlingService(IServiceProvider provider)
        {
            _provider = provider;
        }

        public void Process(Message message)
        {
            
            var commandStr = message.Text.Substring(1).Split(" ");
            ICommand command = null;
            foreach (var service in _provider.GetServices<ICommand>())
            {
                if (((Command) Attribute.GetCustomAttribute(service.GetType(), typeof(Command))).Display.Equals(commandStr[0]))
                {
                    command = service;
                    break;
                };
            }

            command?.Execute(message);
        }
    }


Т.е. по сути сейчас для создания команды мне нужно создать класс и зарегистрировать его в ServiceProvider, а хочется сделать, чтобы для создания команды достаточно было создать класс-реализацию интерфейса. Находил информацию, что можно добавить в serviceprovider циклом то, что мне нужно, но только с Type, а с типами у меня уже ничего не получается.
  • Вопрос задан
  • 274 просмотра
Решения вопроса 1
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы