Calling generic method with a type argument known only at execution time
EDIT: Okay, time for a short but complete program. The basic answer is as before:
- Find the "open" generic method with Type.GetMethod
- Make it generic using MakeGenericMethod
- Invoke it with Invoke
Here's some sample code. Note that I changed the query expression to dot notation - there's no point in using a query expression when you've basically just got a where clause.
using System;
using System.Linq;
using System.Reflection;
namespace Interfaces
{
interface IFoo {}
interface IBar {}
interface IBaz {}
}
public class Test
{
public static void CallMe<T>()
{
Console.WriteLine("typeof(T): {0}", typeof(T));
}
static void Main()
{
MethodInfo method = typeof(Test).GetMethod("CallMe");
var types = typeof(Test).Assembly.GetTypes()
.Where(t => t.Namespace == "Interfaces");
foreach (Type type in types)
{
MethodInfo genericMethod = method.MakeGenericMethod(type);
genericMethod.Invoke(null, null); // No target, no arguments
}
}
}
Original answer
Let's leave aside the obvious problems of calling a variable "interface" to start with.
You have to call it by reflection. The point of generics is to put more type checking at compile time. You don't know what the type is at compile-time - therefore you've got to use generics.
Get the generic method, and call MakeGenericMethod on it, then invoke it.
Is your interface type itself actually generic? I ask because you're calling MakeGenericType on it, but not passing in any type arguments... Are you trying to call
Method<MyNamespace.Interface<string>>(); // (Or whatever instead of string)
or
Method<MyNamespace.Interface>();
If it's the latter, you only need a call to MakeGenericMethod - not MakeGenericType.
How do you call a generic method if you only know the type parameter at runtime?
You need to call it using reflection:
var method = typeof(SomeClass).GetMethod("SomeMethod");
method.MakeGenericMethod(someType).Invoke(...);
How do I use reflection to call a generic method?
You need to use reflection to get the method to start with, then "construct" it by supplying type arguments with MakeGenericMethod:
MethodInfo method = typeof(Sample).GetMethod(nameof(Sample.GenericMethod));
MethodInfo generic = method.MakeGenericMethod(myType);
generic.Invoke(this, null);
For a static method, pass null
as the first argument to Invoke
. That's nothing to do with generic methods - it's just normal reflection.
As noted, a lot of this is simpler as of C# 4 using dynamic
- if you can use type inference, of course. It doesn't help in cases where type inference isn't available, such as the exact example in the question.
Delegate with generic type only known at runtime
I'd advise having generic and non-generic versions of the method, much like List<T>
implements IEnumerable<T>
while also explicitly implementing System.Collections.IEnumerable
.
"Type known only at runtime" is exactly what generics aren't intended to be used for. The way you're calling this method, you only ever get object
out of it anyway. Better to have a real ordinary non-generic method that just returns object
.
T GetOfType<T>();
object GetOfType(Type t);
You don't even need to worry about overload resolution. There's some extra burden placed on the class implementing the interface, admittedly. But as you've seen, there's going to be a burden somewhere.
Call generic method which T is a Type
You want to use the MakeGenericMethod method that is available on MethodInfo, e.g
someTarget.GetType()
.GetMethod("SomeGenericMethod")
.MakeGenericMethod(typeof(SomeGenericArgument)
.Invoke(someTarget, someParameters);
See also:
Calling generic method with a type argument known only at execution time
EDIT - For given example
orderBiz.GetOrderDynamically<tt>(selectExp, predicateExp); – unos
baghaii 5 mins ago
orderBiz.GetType().GetMethod("GetOrderDynamically").MakeGenericMethod(tt).Invoke(orderBiz, new object [] { selectExp, predicateExp });
Function returning a generic type whose value is known only at runtime
typeof(IContainer<>).MakeGenericType(type) will only evaluate at runtime, while "as" needs to know the type at compiler time.
What I really don't understand is this comment: My problem is that I don't know how to enumerate the result which has type Object (therefore I cannot cast it to IEnumerable).
myContainer may be an Object but it can surely be cast to IEnumerable? If it can't then it can't be enumerated.
How to do a generic call to function based on a Type object?
You need to use reflection:
public IEnumerable GetBoxed(Type type, string param1, string param2)
{
return (IEnumerable)this
.GetType()
.GetMethod("Get")
.MakeGenericMethod(type)
.Invoke(this, new[] { param1, param2 });
}
Java determines which method to call using a generic type argument?
What happens here is that the compiler can distinguish the two constructors by using generics, so it does before creating the byte code and before stripping generics.
In the middle case, it will tell the VM to invoke MyClass2<init>(Collection)
(i.e. generate byte code which matches this specific constructor).
The VM doesn't try to determine which method matches at runtime. That would be way too slow. Instead, it relies on the compiler creating very specific instructions.
This is why the code above works even though the generic information has been erased at runtime.
[EDIT] To clarify: The byte code contains additional information which the compiler can see and use. You can get the same information via reflection.
Erasure means that the byte code interpreter and JIT doesn't care about generics which is why you can't have setFoo(List<String>)
and setFoo(List<Integer>)
in the same class: While the compiler could distinguish the two, the runtime can't.
Specifically, when you examine a method via reflection, you will get generics information but the byte code interpreter / JIT doesn't use reflection. Instead, it uses the compressed method signature which reads something like Method com/pany/Type/setFoo(Ljava.util.List;)V
- no generics here anymore.
Related:
- How the Java virtual machine handles method invocation and return
- Why do the Java bytecodes for invoking methods implicitly acquire and release monitors?
- invokevirtual docs
Generic Method Executed with a runtime type
You can, but it involves reflection, but you can do it.
typeof(ClassExample)
.GetMethod("DoSomething")
.MakeGenericMethod(p.DisplayType)
.Invoke(this, new object[] { p.Name, p.Value });
This will look at the top of the containing class, get the method info, create a generic method with the appropriate type, then you can call Invoke on it.
Related Topics
Does Disposing Streamreader Close the Stream
Can a Byte[] Array Be Written to a File in C#
Most Efficient Way to Test Equality of Lambda Expressions
Does the Use of Async/Await Create a New Thread
Method Cannot Be Translated into a Store Expression
How to Pass Values (Parameters) Between Xaml Pages
Finding the Default Application for Opening a Particular File Type on Windows
Use Multiple Jwt Bearer Authentication
How to Convert an Ipv4 Address into a Integer in C#
Typeloadexception Says 'No Implementation', But It Is Implemented
What Is the Use of Observablecollection in .Net
How Do Arrays in C# Partially Implement Ilist<T>
Formatting a Float to 2 Decimal Places
What Is the Purpose of a Marker Interface
Find Size of Object Instance in Bytes in C#
"A Project with an Output Type of Class Library Cannot Be Started Directly"