Instantiate a random class on program start

2019-02-20 11:13发布

问题:

I'm just having a play around with inheritance and a few other concepts at the moment.

I have created a console app that amongst other things, holds the following classes:

Public abstract Organism

Public abstract Animal : Organism

Public Bird : Animal
Public Mammal : Animal
Public Reptile : Animal
Public Fish : Animal
Public Amphibian : Animal

Public Human : Organism

When the console app starts, I want to create a new object from either the Human, Fish, Mammal, Reptile, Bird or Amphibian class. Which one of these classes to instantiate is to be randomly chosen.

Once a class has been randomly chosen, I've used console.writeline to ask the user key questions to assign values to the given objects properties.

How do I create a random object from one of these classes?

回答1:

// use the DLL of the project which is currently running
var runningAssembly = Assembly.GetExecutingAssemby();

// all classes have a "Type" which exposes information about the class
var organismType = typeof(Organism);

// to keep track of all organism classes that we've found.
var allOrganismTypes = new List<Type>();

// go through all types in our project and locate those who inherit our 
// organism class
foreach (var type in runningAssembly.GetTypes())
{
    if (organismType.IsAssignableFrom(type))
        allOrganismTypes.Add(type);
}

// Find a random index here (do it yourself)
var theRandomIndex = 10;


var selectedType = allOrganismTypes[theRandomIndex];

// activator is a class in .NET which can create new objects 
// with the help of a type
var selected = (Organism)Activator.CreateInstance(selectedType);

There are some "mistakes" in the code that you have to correct yourself.



回答2:

If you need to choose types from a list, you could:

Type[] animals = new Type[]{ typeof(Bird), typeof(Mammal), typeof(Reptile), typeof(Fish), typeof(Amphibian) };
Animal animal = animals[new Random().Next(animals.Length)].GetConstructor(new Type[]{}).Invoke(new object[]{}) as Animal;

But for if you value simplicity/readability in your code (and you should), the following is much better if possible:

Animal animal = null;
switch (new Random().Next(5))
{
    case 0:
        animal = new Bird();
        break;
    case 1:
        animal = new Mammal();
...
}

Edit: I forgot about Activator.CreateInstance (simpler than the code I suggested), but using more basic code will be more readable if there aren't very many classes, and allows more flexibility (you don't need every type to have an even probability).



回答3:

Without using Reflection you can achieve it with a List of class Instances:

     var classlist = new List<Organism>();  
    classlist.Add(new Bird());
    classlist.Add(new Mammal());    
    classlist.Add(new Reptile());
    classlist.Add(new Fish());  
    classlist.Add(new Amphibian());
    classlist.Add(new Human());

    var r = new Random();

    var instance = classlist[r.Next(0,5)];