Я вижу много похожих вопросов, но не могу найти решение, охватывающее этот случай:
У меня есть следующий код:
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), и я не понимаю, как может работать метод в этом ответе. Но я был бы рад оказаться неправым.
Вы, вероятно, не можете, использование типов времени выполнения означает использование отражения на всем протяжении. Поэтому, если вы не можете привести полученный объект к чему-то известному во время компиляции, вам придется снова использовать отражение для всех последующих операций.
это определенно неизвестно во время компиляции (плагин). Как я могу использовать отражение, чтобы сделать сложный вызов, подобный тому, что в примере? Я вижу, как создать экземпляр одной части, но не вижу, как вставить ее в цепочку вызовов.
Вы должны получить каждый метод в цепочке, в зависимости от вызова подписи MakeGenericMethod
, а затем Invoke
его.
хорошо, значит, я воссоздаю цепочку вручную, создавая каждую часть?
Да, пожалуйста, попробуйте и задайте конкретные новые вопросы, если это необходимо.
У вас есть общий метод, который вы хотите вызвать. Параметр типа неизвестен во время компиляции, но известен во время выполнения через ссылку Type
. Отмеченный дубликат объясняет, как именно это сделать. Если у вас все еще есть проблемы после просмотра этого, опубликуйте новый вопрос, который включает хороший минимальный воспроизводимый пример, который четко показывает, что вы пробовали, и подробно объясняете, что делает этот код, что вы хотите, чтобы он делал вместо этого, и какой конкретно вы затрудняются разобраться.
Думаю, будет достаточно следующего:
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
});
}
@thehennyy: как бы я использовал метод в этом ответе, чтобы заменить только часть .AddQueryType?