It's a nice approach and really useful especially if you are planning to add level files. Surely a gigantic switch will not work for too many Entities. I think you should use a map. But instead of making it static you can create a class EntityFactory
which will include it.
This EntityFactory
may have two methods. One to create new Entities and one to Add new Entities to the map.
public class EntityFactory
{
private Dictionary<string, Func<Entity>> factoryMethods = new Dictionary<string, Func<Entity>>();
public void RegisterClass<T>(string name) where T : Entity , new()
{
factoryMethods[name] = () => new T();
}
public Entity CreateEntity(string name)
{
return factoryMethods[name]();
}
}
The RegisterClass
method creates a simple function that only calls the constructor of the T
type.
You can use it like this:
factory.RegisterClass<TreeEntity>("tree");
Entity tree = factory.CreateEntity("tree")
Of course you will need at some point to register all your classes. This can be done at the start of your game.
Edit:
This is how you could use this piece of code if you wanted to automatically register all Entity types using reflection:
var assembly = Assembly.GetAssembly(typeof(Entity));
var entityTypes = assembly.GetTypes().Where(t => t.BaseType == typeof(Entity));//get everything that derives from Entity
foreach(var type in entityTypes)
{
string name = type.Name;
//call the generic method of the factory using the type of the entity
MethodInfo method = typeof(EntityFactory).GetMethod("RegisterClass").MakeGenericMethod(new Type[] { type });
method.Invoke(factory, new object[] { name });
}
This will register all classes that derive from Entity with name their class name.
For instance class TreeEntity : Entity
will be registered as "TreeEntity"
Although it works, personally I would not chose this approach. Also one side note, this will only work for all classes that directly derive from Entity
if you need to, you can change the criterion of type selection in Where(t => t.BaseType == typeof(Entity))
.
Again this piece of code should be called at the start of your game.