Specifying Generic Collection Type Param at Runtime

Specifying generic collection type param at runtime

Type generic = typeof(List<>);    
Type specific = generic.MakeGenericType(typeof(int));
ConstructorInfo ci = specific.GetConstructor(Type.EmptyTypes);
object o = ci.Invoke(new object[] { });

Setting generic type at runtime

You can't. Generic type identifiers have to be known at compile time.

edit

as of other posts, it appears to be possible by dynamicly generating the method and invoking it - which has dangers of course. See Thomas' and Dathan's posts for more inforation.

Specifying generic collection type param at runtime (Java Reflection)

Type erasure means that information about the generic type of an object simply isn't present at execution time.

(The link is to the relevant section of Angelika Langer's Java Generics FAQ which should answer virtually every question you could possibly ask about Java generics :)

However, you're not really interested in the type of an object - you're interested in the type of a field. I misread the question, and although the answer has been accepted I hope to make amends by fixing it now :)

If the field doesn't use a type parameter itself, it can be done. For example:

import java.lang.reflect.*;
import java.util.*;

public class Test
{
public List<String> names;

public static void main(String [] args)
throws Exception // Just for simplicity!
{
Field field = Test.class.getDeclaredField("names");

ParameterizedType type = (ParameterizedType) field.getGenericType();

// List
System.out.println(type.getRawType());

// Just String in this case
for (Type typeArgument : type.getActualTypeArguments())
{
System.out.println(" " + typeArgument);
}
}
}

If the field were in a class T with the field being List<T> then you'd have to know the type argument for the instance in order to know the type argument for the collection.

Translating this into your required code is somewhat tricky though - you really need to know the type argument at the point of the collection class. For instance, if someone declared:

public class StringCollection implements Collection<String>

and then had a field of type StringCollection, that field itself wouldn't have any type arguments. You'd then need to check getGenericSuperType and getGenericInterfaces recursively until you found what you wanted.

It's really not going to be easy to do that, even though it's possible. If I were you I'd try to change your design so that you don't need this.

How to set the generic type of an ArrayList at runtime in java?

You can't.

Generics in Java are simply compile-time syntactic sugar. It makes it so you don't have to cast everything to and from Object like we did in the old days when dinosaurs roamed the JVM, and gives you some compile-time type checking.

Edit to add: There is some metadata preserved at runtime that you can get at via reflection to inspect a generic class, but nothing like what you want.

Passing a Type to a generic method at runtime

You can use reflection and construct your call like this:

Type MyType = Type.GetType(FromSomewhereElse);

var typeOfContext = context.GetType();

var method = typeOfContext.GetMethod("GetList");

var genericMethod = method.MakeGenericMethod(MyType);

genericMethod.Invoke(context, null);

Note that calling methods with reflection will add a huge performance penalty, try to redesign your solution if possible.

generic class, how to set the type in runtime?

You can create your class in another way, passing to the constructor the type that you want to use and exploit the dynamic keyword.

For example:

class MyGeneralClass
{
dynamic myVariable;
Type type;

public MyGeneralClass(Type type)
{
this.type = type;
myVariable = Activator.CreateInstance(type);
//And then if your type is of a class you can use its methods
//e.g. myVariable.MyMethod();
}

//If your function return something of type you can also use dynamic
public dynamic Function()
{
return Activator.CreateInstance(type);
}
}

How to cast a generic type at runtime in c#

OK, based on Master Morality's answer, I've come up with this. Shockingly simple.

public static IEnumerable Cast(this IEnumerable self, Type innerType)
{
var methodInfo = typeof (Enumerable).GetMethod("Cast");
var genericMethod = methodInfo.MakeGenericMethod(innerType);
return genericMethod.Invoke(null, new [] {self}) as IEnumerable;
}

Simple. Blogged about it here: Casting an enumerable when the inner type is only known at runtime

How do I build a Java type object at runtime from a generic type definition and runtime type parameters?

I think I understand your question. You want to serialize a Foo<T>, and you have the class object of T at runtime (but it's not fixed at compile time). Therefore, the suggested solution in Gson of creating an anonymous subclass of TypeToken does not work because that requires that the parameterized type (e.g. Foo<String>) be hard-coded at compile time, and it does not work if you use something like Foo<T>.

However, let's look at what the TypeToken method on the Gson site actually accomplishes. You create an object of an anonymous subclass of TypeToken, and then ask for its type parameter using its getType() method. A class's superclass is part of its metadata, and includes the generic parameters of its superclass. So at runtime, it can look at its own inheritance hierarchy, and figure out what type parameter you used for TypeToken, and then returns a java.lang.reflect.Type instance for that type (which, if it is parameterized, will be a ParameterizedType instance). Once you get this Type instance, you are supposed to pass it as the second argument of the toGson().

All we need to do is find another way to create this instance of ParameterizedType. ParameterizedType is an interface, but unfortunately the public Java API does not provide any concrete implementations or any way to create a ParameterizedType dynamically. There appears to be a class called ParameterizedTypeImpl, in the private Sun APIs and in the Gson code that you can use (e.g. here). You can simply copy the code and rename it into your own class. Then, to create a Type object representing Foo<String> at runtime, you can just do something like new ParameterizedTypeImpl(Foo.class, new Type[]{String.class}, null) (untested)



Related Topics



Leave a reply



Submit