How to define Type T for List<T> at runtime

G

Guest

I am looking for a way to do something similar to

public void CreateList()
{
Type[] dataTypes =
{
typeof(int), typeof(string)
};

Dictionary<string, object> mylist = new Dictionary<string, object>();

foreach ( Type y in dataTypes )
{
mylist.Add( y.Name, new List<y>() );
}
}

For reference, I ** WILL NOT ** be using the System.Data types. I will
be using custom classes.

Thanks,
Dave
 
C

Carl Daniel [VC++ MVP]

Webbert said:
I am looking for a way to do something similar to

public void CreateList()
{
Type[] dataTypes =
{
typeof(int), typeof(string)
};

Dictionary<string, object> mylist = new Dictionary<string, object>();

foreach ( Type y in dataTypes )
{
mylist.Add( y.Name, new List<y>() );
}
}

For reference, I ** WILL NOT ** be using the System.Data types. I
will be using custom classes.

Thanks,
Dave
 
C

Carl Daniel [VC++ MVP]

Webbert said:
I am looking for a way to do something similar to

public void CreateList()
{
Type[] dataTypes =
{
typeof(int), typeof(string)
};

Dictionary<string, object> mylist = new Dictionary<string, object>();

foreach ( Type y in dataTypes )
{
mylist.Add( y.Name, new List<y>() );
}
}

Take a look at System.Type.MakeGenericType to create a concrete Type from an
unspecialized generic type.

-cd
 
G

Guest

Using your suggestion of MakeGenericType, I came up with the following demo.
While this works, is it necessarily the best/correct way to do it?

Thanks,
Dave

==================

using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Reflection;

namespace ConsoleApplication1
{
class Program
{
Dictionary<string, object> mylist = new Dictionary<string, object>();
private List<object> sampleData = new List<object>();

private Type[] dataTypes =
{
typeof(int),
typeof(string)
};

static void Main( string[] args )
{
Program p = new Program();
p.CreateList();
p.FillList();
p.DiplayList();

Console.Out.WriteLine( "\n\nPress enter to continue..." );
Console.In.ReadLine();
}


public Program()
{
sampleData.Add( 1 );
sampleData.Add( "Hello" );
sampleData.Add( 2 );
sampleData.Add( "World" );
}

public void CreateList()
{
foreach ( Type type in dataTypes )
{
Type newList = typeof( List<> ).MakeGenericType( type );

BindingFlags internalFlags =
BindingFlags.CreateInstance |
BindingFlags.Public |
BindingFlags.Instance;

object instance = Activator.CreateInstance(
newList, internalFlags, null, null, null, null );

mylist.Add( type.Name, instance );
}
}

public void FillList()
{
Type listType;
IList list;

foreach ( object data in sampleData )
{
listType = data.GetType();

list = mylist[listType.Name] as IList;
if ( list != null )
{
list.Add( data );
}
}
}

public void DiplayList()
{
foreach ( string keys in mylist.Keys )
{
IList list = mylist[keys] as IList;
foreach ( object data in list )
{
Console.Out.WriteLine( data.ToString() );
}
}
}
}
}
 
C

Carl Daniel [VC++ MVP]

Webbert said:
Using your suggestion of MakeGenericType, I came up with the
following demo. While this works, is it necessarily the best/correct
way to do it?

It's the right way to create instantiations of a generic type at runtime.

The question I'd have is why go to the trouble to create strongly typed
lists when you're only ever accessing them in weakly typed way? You could
just use System.Collections.ArrayList everywhere and have significantly
simpler (although slightly less efficient) code.

Of course, if there's some other aspect to the real problem you're trying to
solve that benefits from having strongly typed containers, then there's
nothing wrong with this approach.

-cd
 
G

Guest

I am doing a 2-way transformation between a 3rd party xml schema and my
system. Everything in their schema at the top level is optional which
basically turns into an object[]. With that in mind, I will have to iterate
over my list and put everything back into the object[]. So, I am providing 2
methods to work with.

One to iterate over an array of object types Type[] aTypes = {
typeof(string) ... }
foreach ( Type xyz in aTypes )
{
IList myvar = RetrieveList(xyz);
}

public IList RetrieveList( Type type )
{
return ( mylist[type.Name] as IList );
}

And one to use for tighter typing.

public List<T> RetrieveList<T>()
{
return ( mylist[typeof( T ).Name] as List<T> );
}

public List<Address> Address
{
get { return ( RetrieveList<Address>() ); }
}


I provided the first method because, to the best of my knowledge, I am
restricted from doing something like:
foreach ( Type xyz in aTypes )
{
List<xyz> myvar = RetrieveList<xyz>();
}


Thanks for your assistance.


Dave
 
C

Carl Daniel [VC++ MVP]

Webbert said:
I provided the first method because, to the best of my knowledge, I am
restricted from doing something like:
foreach ( Type xyz in aTypes )
{
List<xyz> myvar = RetrieveList<xyz>();
}

Yep, you're right - the ty pe parameters to a generic type must be
compile-time constants, otherwise you have to go through
Type.MakeGenericType().

-cd
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top