tags:

views:

87

answers:

3

I am writing a game editor, and have a lot of different "tool" objects. They all inherit from BTool and have the same constructor.

I would like to dynamically populate a toolbox at runtime with buttons that correspond to these tools, and when clicked have them create an instance of that tool and set it as the current tool.

Is this possible, and if so will it be better/easier than creating those buttons by hand?

+4  A: 

Yes.

To find the tools, you can call Assembly.GetTypes:

var toolTypes = typeof(Tool).Assembly.GetTypes()
    .Where(t => typeof(Tool).IsAssignableFrom(t))
    .ToArray();

To create the tools, you can call Activator.CreateInstance:

obj = Activator.CreateInstance(type, arg1, arg2);
SLaks
Thanks, nice and easy, just what I wanted!
Homeliss
+2  A: 

If you're using .NET 3.5, I'd go check out MEF (Managed Extensibility Framework) and if you're using .NET 4.0 then MEF is already built in.

In a nutshell, this is all you would have to do. (Plus of course some simple code to "kick off" the composition. It's all on the MEF site linked above.)

[InheritedExport]
public abstract class BTool {
}

public class HandTool : BTool {
}

public class LassoTool : BTool {
}

public class Game {

    [ImportMany]
    public List<BTool> Tools {
        get;
        set;
    }

}
Josh Einstein
A: 

You will have to instantiate each object.

However, you can then implement a 'clicked' method for a set of buttons, something like:

List<BTool> theTools = new List<BTool>();
BTool mapTool1 = new MapTool1(); //assumes that MapTool1 inherits from BTool
BTool mapTool2 = new MapTool2(); 
//and so on

If you're using WPF or WinForms, the exact code will be slightly different. Assuming you're using WPF, you'll do something like this in the xaml:

<StackPanel Name="ToolButtons" /> //make sure to orient your tools how you like, vertical or horizontal

and then in the constructor of the WPF form:

foreach (BTool b in theTools){
   Button button = new Button();
   button.Title = b.Name; //or .ToString, whatever
   button.Clicked += b.ClickedEvent; //where ClickedEvent is a method in BTool that implements the interface for the Clicked event
   ToolButtons.Children.Add(button);
}
mmr