-1

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

I have the following code:

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


public class Test
{
    ...
}

it's not my code and it can't be changed.

Since the system has a plugin architecture, I cannot know the Test type ahead of time, so I need to do something like:

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

but I can't find how to make this work.

I tried to pass typeof, I tried to create an instance with Activator.CreateInstance, etc and I can't find how to make this happen.

How can this be done?


Edit:

This was flagged as a possible duplicate of How do I use reflection to call a generic method?, although the first line of my question said:

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

The answer in the other question is calling one method based on its name. Here the place to inject the type is in the middle of a chain (between AddQuery and Register) and I don't see how the method in that answer could work. But I'd be happy to be proven wrong.

Thomas
  • 10,933
  • 14
  • 65
  • 136
  • @thehennyy: how would I use the method in that answer to replace just the .AddQueryType part? – Thomas Jul 29 '19 at 12:31
  • You probably can't, using runtime types means using reflection all the way through. So if you can not cast the resulting object to something known at compile time you have to use reflection again for all following operations. – thehennyy Jul 29 '19 at 12:35
  • it's definitely not known at compile time (plug-in). How could I use reflection to make a complex call like the one in the example though? I can see how to instantiate one part, but not how to insert that in the chain of calls. – Thomas Jul 29 '19 at 12:37
  • You have to get each method in the chain, depending on the signature call `MakeGenericMethod` and then `Invoke` it. – thehennyy Jul 29 '19 at 12:39
  • ok, so I recreate the chain manually by instantiating every part? – Thomas Jul 29 '19 at 12:40
  • 1
    Yes, please give it a try and ask specific new questions if needed. – thehennyy Jul 29 '19 at 12:41
  • You have a generic method you want to call. The type parameter is not known at compile time, but is known at runtime via a `Type` reference. The marked duplicate explains exactly how to do that. If you are still having problems after reviewing that, please post a new question which includes a good [mcve] that shows clearly what you've tried, and explain in detail what that code does, what you want it to do instead, and what _specifically_ you are having trouble figuring out. – Peter Duniho Jul 30 '19 at 02:39

1 Answers1

0

I guess the following would suffice:

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
  });
}
Sohaib Jundi
  • 1,576
  • 2
  • 7
  • 15