Передача типа в качестве параметра в API, который принимает общий тип

Я вижу много похожих вопросов, но не могу найти решение, охватывающее этот случай:

У меня есть следующий код:

Service.AddQuery(T => new ServiceFactory.New()
    .AddQueryType<Test>()
    .Register(T)
    .Create());


public class Test
{
    ...
}

это не мой код и его нельзя изменить.

Поскольку система имеет плагиновую архитектуру, я не могу заранее знать тип теста, поэтому мне нужно сделать что-то вроде:

RegisterService(Type MyQueryType)
{
    Service.AddQuery(T => new ServiceFactory.New())
        .AddQueryType<MyQueryType>()
        .Register(T)
        .Create());
}

но я не могу найти, как заставить это работать.

Я пытался передать typeof, пытался создать экземпляр с помощью Activator.CreateInstance и т. д. и не могу найти, как это сделать.

Как это может быть сделано?


Редактировать:

Это было помечено как возможный дубликат Как использовать отражение для вызова универсального метода?, хотя первая строка моего вопроса гласила:

I can see many similar questions, but I can't find a solution covering this case

Ответ на другой вопрос вызывает один метод на основе его имени. Здесь место для ввода типа находится в середине цепочки (между AddQuery и Register), и я не понимаю, как может работать метод в этом ответе. Но я был бы рад оказаться неправым.

@thehennyy: как бы я использовал метод в этом ответе, чтобы заменить только часть .AddQueryType?

Thomas 29.07.2019 14:31

Вы, вероятно, не можете, использование типов времени выполнения означает использование отражения на всем протяжении. Поэтому, если вы не можете привести полученный объект к чему-то известному во время компиляции, вам придется снова использовать отражение для всех последующих операций.

thehennyy 29.07.2019 14:35

это определенно неизвестно во время компиляции (плагин). Как я могу использовать отражение, чтобы сделать сложный вызов, подобный тому, что в примере? Я вижу, как создать экземпляр одной части, но не вижу, как вставить ее в цепочку вызовов.

Thomas 29.07.2019 14:37

Вы должны получить каждый метод в цепочке, в зависимости от вызова подписи MakeGenericMethod, а затем Invoke его.

thehennyy 29.07.2019 14:39

хорошо, значит, я воссоздаю цепочку вручную, создавая каждую часть?

Thomas 29.07.2019 14:40

Да, пожалуйста, попробуйте и задайте конкретные новые вопросы, если это необходимо.

thehennyy 29.07.2019 14:41

У вас есть общий метод, который вы хотите вызвать. Параметр типа неизвестен во время компиляции, но известен во время выполнения через ссылку Type. Отмеченный дубликат объясняет, как именно это сделать. Если у вас все еще есть проблемы после просмотра этого, опубликуйте новый вопрос, который включает хороший минимальный воспроизводимый пример, который четко показывает, что вы пробовали, и подробно объясняете, что делает этот код, что вы хотите, чтобы он делал вместо этого, и какой конкретно вы затрудняются разобраться.

Peter Duniho 30.07.2019 04:39
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
7
41
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Думаю, будет достаточно следующего:

RegisterService(Type MyQueryType)
{
  Service.AddQuery(T =>
  {
    var service = new ServiceFactory.New();
    var method = service.GetType().GetMethod("AddQueryType").MakeGenericMethod(new Type[] { MyQueryType });
    var result = /*cast to AddQueryType return type*/method.Invoke(service, null);
    return result.Register(T).Create(); //if Create is void, remove the return
  });
}

Другие вопросы по теме