Click to See Complete Forum and Search --> : Reflection for generics .NET 2.0
Autofreak
April 22nd, 2008, 05:52 PM
Hello,
I have a generic collection class.
public class CustomTypeCollection<T>: ICustomTypeCollection<T>, IEnumerable<T> where T:class,ICustomType, new()
{
List<T> collection=new List<T>();
public CustomTypeCollection()
{
}
public void Add(T item)
{
collection.Add(item);
}
public T Item(int index)
{
return collection[index];
}
IEnumerator IEnumerable.GetEnumerator()
{
{ return collection.GetEnumerator(); }
}
IEnumerator<T> IEnumerable<T>.GetEnumerator()
{
{ return collection.GetEnumerator(); }
}
T type is not known at compile. I would like to be able to dinamically set it up at runtime. Is there a way to accomplish it nicely?
Thank you,
Serge
someuser77
April 22nd, 2008, 11:50 PM
I wasn't able to compile CustomTypeCollection because the compiler did not find ICustomType, but still, this code should get you started as it creates an instance of CustomTypeCollection where T is a System.Int32.
(I tested it on "public class CustomTypeCollection<T> : IEnumerable<T>"):
Type genericType = typeof(CustomTypeCollection<>);
Type constructedType = genericType.MakeGenericType(Type.GetType("System.Int32", true));
object generic = Activator.CreateInstance(constructedType);
generic.GetType().GetMethod("Add").Invoke(generic, new object[] { 1 });
MadHatter
April 23rd, 2008, 09:37 AM
you should also note that generics are not templates and are not assembled at compile time (your comment that T wasn't known at compile time prompted this comment).
Autofreak
April 24th, 2008, 02:22 PM
you should also note that generics are not templates and are not assembled at compile time (your comment that T wasn't known at compile time prompted this comment).
Hello MadHatter,
Does that mean that it's only natural to let the generic class instance know the exact type <T> just before it gets instanciated at run? Would you be able to see that process thru examinig IL modules?
Thank you.
Serge
JonnyPoet
April 24th, 2008, 05:51 PM
Hello MadHatter,
Does that mean that it's only natural to let the generic class instance know the exact type <T> just before it gets instanciated at run? Would you be able to see that process thru examinig IL modules?
Thank you.
SergeI would intensify your statement and say its not only natural it is not possible to have a generic class used in code without defining T in the moment where you are using it by any code. Sure you can use a generic class in another generic code. As you did for example by using List <T> in your code. But the class itself is still generic then. But for any 'real' usage ( other then as a part of another generic class) you have to define what T exactly is. Constraints and Interfaces will help you to to a lot in your generic classes and methods, but at least the whole sense of any generic code is to use it together with nongeneric class objects:D
Autofreak
April 28th, 2008, 10:12 AM
I wasn't able to compile CustomTypeCollection because the compiler did not find ICustomType, but still, this code should get you started as it creates an instance of CustomTypeCollection where T is a System.Int32.
(I tested it on "public class CustomTypeCollection<T> : IEnumerable<T>"):
Type genericType = typeof(CustomTypeCollection<>);
Type constructedType = genericType.MakeGenericType(Type.GetType("System.Int32", true));
object generic = Activator.CreateInstance(constructedType);
generic.GetType().GetMethod("Add").Invoke(generic, new object[] { 1 });
Thank you someuser77, You solution is very helpful
I also tried to cast 'generic' to a real class/interface in order to get the advantage of compile time and intellisense but realized that it's impossible. There is no inferitace/poltmorthysm relationship between two generic classes even if the generic types of those are in the inheritance hierarchy.
I decided to go with a concrete collection class with List<AbstractBaseClass> in it to implement the collection functionality. I figured that I am going to use only custom classes that implement a certain behaviour 'A' anyway. This bahavior of any such class is going to be restricted by AbstractBaseClass. If anybody attempts to pass a class that doesn't inherit from AbstractBaseClass it will be disallowed at compile.
Thank you,
Serge
Autofreak
April 28th, 2008, 10:13 AM
I would intensify your statement and say its not only natural it is not possible to have a generic class used in code without defining T in the moment where you are using it by any code. Sure you can use a generic class in another generic code. As you did for example by using List <T> in your code. But the class itself is still generic then. But for any 'real' usage ( other then as a part of another generic class) you have to define what T exactly is. Constraints and Interfaces will help you to to a lot in your generic classes and methods, but at least the whole sense of any generic code is to use it together with nongeneric class objects:D
Thank you, I think I got it.
Serge
Mutant_Fruit
April 28th, 2008, 01:30 PM
Thank you someuser77, You solution is very helpful
I also tried to cast 'generic' to a real class/interface in order to get the advantage of compile time and intellisense but realized that it's impossible.
IList<T> inherits from IList, so you can cast the object to IList.
EDIT: Sorry, just realised you weren't inheriting from IList<T>. I thought you were.
MadHatter
April 28th, 2008, 04:28 PM
Thank you someuser77, You solution is very helpful
I also tried to cast 'generic' to a real class/interface in order to get the advantage of compile time and intellisense but realized that it's impossible. There is no inferitace/poltmorthysm relationship between two generic classes even if the generic types of those are in the inheritance hierarchy.
I decided to go with a concrete collection class with List<AbstractBaseClass> in it to implement the collection functionality. I figured that I am going to use only custom classes that implement a certain behaviour 'A' anyway. This bahavior of any such class is going to be restricted by AbstractBaseClass. If anybody attempts to pass a class that doesn't inherit from AbstractBaseClass it will be disallowed at compile.
Thank you,
Serge
it is actually possible.
public class MyClass<T> where T : /* SomeBaseClass, */ IComparable {
T instance;
public int Compare(T somethingElse) {
return instance.CompareTo(somethingElse);
}
}
what you need to do is define the base types that must be true for T. the syntax is:
where T : <param list>
param list can be a number of things, a short list is:
BaseClass, InterfaceA, InterfaceB, ...
new()
class
struct
so basically, you can define what T inherits (line 1) just like you would define what a class inherits: base class first if there is any, comma separated interface list
you can specify that the type has to have a public default constructor w/ new()
you can define that T be a reference type using the class keyword
you can define that T be a value type by using the struct keyword.
once you do that, you can refer to T as though it were the base class (visual studio will add in methods from the base type or interface list). if it implements new() you can say: T instance = new T(); if T implements class, you can check for null and so on...
I hope that helps some. in the editor it feels somewhat similar to templates, but the actual implementation is quite different. when using reflection to create some generic type, if you don't specify parameters you'll end up with a null instance and it won't work. when doing things in the editor the compiler will complain if things aren't up to par.
codeguru.com
Copyright Internet.com Inc., All Rights Reserved.