I'm developing a game in C# on Unity that aims to learn basics in Python.
In my project I have created an abstract class Execution which defines the different types of executions in Python :
public abstract class Execution
{
public enum ExecutionType
{
Affectation,
Incrementation,
Decrementation,
Multiplier,
Divisor,
EntireDivisor,
Modulo,
IfStatement,
ElseStatement,
ForLoop,
WhileLoop,
Pass,
}
public ExecutionType Type;
public abstract string Representation();
public Execution(ExecutionType type)
{
type = Type;
}
// Some others methods
}
And here is an example of a class that derives from Execution :
public class Pass : Execution
{
public Pass() : base(ExecutionType.Pass) { }
public override string Representation()
{
return IndentRepresentation($"<color=#eb8f34>pass</color>");
}
}
All this allows me to create a random Python code generator in another script, so I started to think about an algorithm that allows to generate a Python code that works by instantiating for each line a class derived from the Execution class.
int randomIndex = 0; // Generated in the algorithm
List<Type> ExecutionsTypes = new List<Type>();
ExecutionsTypes.Add(typeof(Affectation)); // Error
ExecutionsTypes.Add(typeof(Pass));
Execution execution = (Execution)Activator.CreateInstance(ExecutionsTypes[randomIndex]); // Sometimes errors
My problem is that I want to store all the types of these classes in a list and be able to instantiate them by browsing the list but yet, some classes are generic classes (so I have an error in those places) but others have necessary arguments, and since the choice is random, I can't know how to put the necessary arguments.
CodePudding user response:
In order to use Activator.CreateInstance(someType)
each type must have a parameterless constructor. You indicated that sometimes you get an error, so it's apparent that some of your classes don't. Even if they did that's a difficult design because later you might want to add a type without a default constructor and you won't be able to.
One approach is to create a list of instantiated classes instead of a list of types.
Instead of this:
List<Type> executionsTypes = new List<Type>();
executionsTypes.Add(typeof(Affectation));
executionsTypes.Add(typeof(Pass));
do this:
List<Execution> executions = new List<Execution>();
executions.Add(new Affectation());
executions.Add(new Pass());
Then instead of selecting a type from the list and having to instantiate it, you can select a class instance that's already been instantiated.
What if you don't want to re-use class instances and you need a new one each time? Then you could do this:
List<Func<Execution>> executions = new List<Func<Execution>>();
executions.Add(() => new Affectation());
executions.Add(() => new Pass());
executions.Add(() => new SomeTypeWithParameters("x", 1));
Then what you select from the list is a function that returns an Execution
, and you call it to create a new instance.
Func<Execution> createExecutionFunction = // however you randomly select one
Execution execution = createExecutionFunction();