How do you get the argument value supplied to a closed/constructed generic method?
It's been a while since I haven't touched Reflection. All this used to be at the back of my, umm, whatever.
class Program
{
static void Main(string[] args)
{
new ConcreteFoo().GenericMethod<int>(5);
Console.ReadKey();
}
}
class ConcreteFoo
{
public void GenericMethod<Q>(Q q)
{
var method = MethodInfo.GetCurrentMethod();
var parameters = method.GetParameters();
if (parameters.Length > 0)
foreach (var p in parameters)
Console.WriteLine("Type: {0}", p.ParameterType);
// That still prints Q as the type.
// I've tried GetGenericArguments as well. No luck.
// I want to know:
// 1) The closed type, i.e. the actual generic argument supplied by the caller; and
// 2) The value of that argument
}
public void GenericMethodWithNoGenericParameters<Q>()
{
// Same here
}
}
class GenericFoo<T>
{
public void NonGenericMethod(T t) { /* And here*/ }
public void GenericMethod<Q>(Q q) { /* And here */ }
}
UPDATE
This question is absurd and hence closed by the asker. He wishes to retain it just to show his children how stupid daddy was, if they ever turned out to be C# programmers.
The short answer is, that there is no way to find out the runtime type of generic type parameters in Java. A solution to this is to pass the Class of the type parameter into the constructor of the generic type, e.g.
The generic argument list is a comma-separated list of type arguments. A type argument is the name of an actual concrete type that replaces a corresponding type parameter in the generic parameter clause of a generic type. The result is a specialized version of that generic type.
A generic type is a generic class or interface that is parameterized over types.
The short answer is typeof(Q).
The long answer (which tries to explain why you can't enumerate these types and you must write them specifically) goes like this:
Each generic method (which is more generic than it's declaring class) has corresponding, distinct MethodInfo instances for all of its (ever) touched particularizations and another MethodInfo for the "template"/open method.
You could use this to obtain what you want:
class ConcreteFoo {
public void GenericMethod<Q>(Q q) {
var method = MethodInfo.GetCurrentMethod();
var closedMethod = method.MakeGenericMethod(typeof(Q));
// etc
}
}
Why is that ? It's because none of the "enumerating operations" in reflection return MethodInfo instances that refer to closed particularizations.
If you enumerate the static methods declared by ConcreteFoo like so:
var atTime1 = typeof(ConcreteFoo).GetMethods(BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly);
ConcreteFoo.GenericMethod( true );
var atTime2 = typeof(ConcreteFoo).GetMethods(BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly);
you will get identical results. As far as GenericMethod and it's entourage of particularizations are concerned, you will get only the reflection object associated with GenericMethod (open variant).
atTime2 will not contain an extra MethodInfo referring to the freshly jitted GenericMethod< bool >.
But that not's really a bad thing, now is it ? GetMethods() should return consistent results and not have its results vary in time. The algebra of generic methods is actually quite nice when it comes to it's "navigation" operations:
The same goes for the reflection operations that come from the current thread's perspective (rather than from that of the assemblies and types):
MethodBase MethodInfo.GetCurrentMethod()
and
StackTrace trace = new StackTrace();
IEnumerable<MethodBase> methods = from frame in trace.GetFrames()
select frame.GetMethod();
never return the actual closed variants of generic methods (if any) that are actually on the top, or throughout the current call stack.
In a way your question is not absurd, because, while in the case of GetCurrentMethod you could easily replace it with GetCurrentMethod plus MakeGenericMethod plus the syntactically available typeof(Whatever), you can't say that about your callers.
So.. for non-generic methods you can always look at your stack and know precisely what are those methods' parameter types. The methods that invoked each other and eventually yours got invoked... But for generic ones (which are really truly closed, for I repeat it is illogical to think that a generic method that runs and calls another and was called by someone else (etc) is an open one) you can't find out the types of the parameters just like you can't learn the values of any such methods' local variables (which are deterministic but it would be a great flaw in performance to make that a possibility).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With