tags:

views:

428

answers:

4

I'm making a simple test object-oriented program to try and help me get to grips with OOP. I've got an ICommand inteface which has the method Run(params object[] parameters) and I have various classes that use that interface and implement their own versions of run. Each class also has a name property which says what the command is and what it does.

I want to have a GUI where I can create commands, which presumably will need some sort of listbox to select what type of command to create. The question is, how do I make that listbox and make it work without hardcoding in a switch statement with explicit references to all of the classes I've created.

I'm sure this is a really simple problem that I should know the answer to, but I just can't think of it! I'm sure there is an answer though.

Oh and I expect some of the responses will say to read the Design Patterns book: well the only copy in the library is out at the moment, but I will be reading it asap!

Update: I've just posted a follow up question here

+1  A: 

Store all your classes in a generic list of ICommand , override ToString() with the name of your command and apply the contents of the list to your listbox.

var commandlist = new List<ICommand>();
commandList.add(new Command("Run"));
commandList.add(new Command("Walk"));
commandList.add(new Command("Crawl"));
John Nolan
Thanks for the response. Sadly I don't quite understand what you mean. What is a generic list of ICommand?
robintw
added some code. Command is a class that implements ICommand.
John Nolan
I've just posted a follow up question here: http://stackoverflow.com/questions/454163/c-polymorphism-load-classes-from-dll-files
robintw
+1  A: 

Hey robintw,

use the strategy pattern (link to wikipedia), you'll execute the method via invoke or reflection. Since there are a lot of examples i won't list here.

Kamia
A: 

You could use reflection to find all the classes that implement the interface you're interested in; then use that to populate your list

Rowland Shaw
+1  A: 

I'm not sure you really need to avoid the explicit invocation of constructors. However, you can do it through reflection - if the constructors of your types don't need any arguments:

 var commands = new List<object>();
 foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
 {
    foreach (Type type in assembly.GetTypes())
    {
       if (type.GetInterface(typeof(ICommand).FullName) != null)
       {
          commands.Add(Activator.CreateInstance(type));
       }
    }
 }

This code assumes the assemblies defining the ICommand implementations are already loaded and does not do any desired error handling.

Another approach is to read a configuration file with the names of the types to instantiate (and maybe even of assemblies to load).

However, in most cases there is no need for this. It's typically quite alright to have a CommandFactory class which just calls a bunch of constructors.

Wim Coenen