Здравствуйте. Несколько суток не дает нормально жить одна проблема.
Есть .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, а с типами у меня уже ничего не получается.