1

I want to have a dictionary of class instances like this:

Dictionary<string, class> dictionary = new Dictionary<string, class>();

// Load all classes of a namespace
Type[] typelist = GetTypesInNamespace(Assembly.GetExecutingAssembly(), "GameStates");
for (int i = 0; i < typelist.Length; i++)
{
    Console.WriteLine(typelist[i].Name);
    gameStateList.Add(typelist[i].Name, typelist[i]);
}

dictionary["ClassA"].MethodB(5); // Doesn't work

How could I do that?

Chris Leyva
  • 3,478
  • 1
  • 26
  • 47
Adrien Neveu
  • 827
  • 1
  • 15
  • 28
  • 4
    This is currently invalid code - `class` is a keyword. And you're not creating any instances at all. – Jon Skeet Feb 17 '14 at 19:13
  • I know, that was an example as I don't know how to do it. – Adrien Neveu Feb 17 '14 at 19:14
  • 1
    Well if you're saying something "doesn't work" that suggests the code before it is valid - in this case, it isn't. – Jon Skeet Feb 17 '14 at 19:16
  • See http://msmvps.com/blogs/jon_skeet/archive/2008/10/08/mapping-from-a-type-to-an-instance-of-that-type.aspx for a blog post about this though. – Jon Skeet Feb 17 '14 at 19:16
  • Can you provide more informations on what you want to accomplish? Perhaps there's a better and easier way to achieve the same results. – Crono Feb 17 '14 at 19:24

2 Answers2

5

Note that there are two different things in C#. A class specification, which describes a class, is contained in a Type object. A class instance, which describes a particular object, is an object or any derived class.

There are some additional issues with your code, but I think you can solve them yourself once you get how types and instances work.


In this case, GetTypesInNamespace returns a list of Type objects, thus class specifications. You can put them in a dictionary if you want.

Dictionary<string, Type> dictionary = new Dictionary<string, Type>();

Then, if you want to make the class specification into an instance, you have to call the class constructor. You can use reflection on the Type for that.

// Get the type.
Type someType = dictionary["ClassA"];

// Create an instance.
object myInstance = Activator.CreateInstance(someType);

Note that the above example works for classes that have a default parameterless constructor. If your classes have constructors with parameters, look at the Activator.CreateInstance method's documentation to find out how to pass those parameters.


Now you want to call MethodB on the instance. There are three ways to do this.

  1. You know the type of the instance, and you cast the instance to the correct type.

    ClassA myClassA = (ClassA)myInstance;
    myClassA.MethodB(5);
    
  2. You don't know the type of the instance, but you know it has a method MethodB, and you're using .NET 4 or newer.

    dynamic myDynamicInstance = (dynamic)myInstance;
    myInstance.MethodB(5);
    

    When the instance' class doesn't have a MethodB, you'll get an exception.

  3. Using reflection. This is a bit more complicated. Search around if you need it. I think dynamic is the way to go for you here.

Community
  • 1
  • 1
Daniel A.A. Pelsmaeker
  • 47,471
  • 20
  • 111
  • 157
2

Since you are talking about class instances, the best you can do without knowing anything else is a dictionary of objects:

Dictionary<string, object> dict;

But this is not going to be useful at all since you want to call methods on them. It is better to have your states implement a certain interface so that you can call the appropriate method:

Dictionary<string, IGameState> dict;

You can then fill this dictionary just like Virtlink explained in his nice answer.

BlackBear
  • 22,411
  • 10
  • 48
  • 86