0

I have base class Animal, and I created many classes which inherits from it, such as Dog, Cat, Monkey ... now I want to implement the feature that based on user input, create the object based on the input so that I can run the override version functions inside them. Something like that:

//Animal.cs
abstract class Animal
{
    protected abstract void Func()
}

//Dog(or other animal).cs
class Dog:Animal
{
    protected override void Func() {Do something;}
}

//program.cs
public static void main()
{
    Animal a = null;
    string str = Console.ReadLine();
    a = "new str()"; // should have some try-catch module, omit here       
}

I have hundreds of animals, so using if or switch does not look a good solution; any good methods?

4
  • 3
    Possible duplicate of Create an instance of a class from a string Commented Sep 28, 2018 at 10:00
  • Create a string[](or an enum) of possible inputs, let the user know if he didn't type one that is in this list. If he selected an available use a switch to create the right animal. Reflection is a bad approach imo Commented Sep 28, 2018 at 10:03
  • @TimSchmelter op was looking for options besides switch and if. Reflection is one of them but also a debatable topic on its own. Commented Sep 28, 2018 at 10:19
  • @cl0ud: what other option than reflection you have? Commented Sep 28, 2018 at 10:23

1 Answer 1

4

One way do this would be to use a factory using reflection at runtime. Its not the neatest but will avoid you having to use if statements.

 public static class AnimalFactory
{
    public static Animal Create(string animalName)
    {
        var type = Type.GetType(typeof(Animal).Namespace + "." + animalName, throwOnError: false);

        if (type == null)
        {
            throw new InvalidOperationException(animalName.ToString() + " is not a known Animal type");
        }

        if (!typeof(Animal).IsAssignableFrom(type))
        {
            throw new InvalidOperationException(type.Name + " does not inherit from Animal");
        }

        return (Animal)Activator.CreateInstance(type);
    }
}

Based upon your namespace it will create an instance of an animal using reflection. You can pass in the animal name from your user input.

Then call it using

var type = AnimalFactory.Create("dog");
Sign up to request clarification or add additional context in comments.

1 Comment

I would include a singleton cache also since reflection is an expensive operation. If the number calls run into the thousands performance will degrade without lookups. This code requires that the "animalName" value is consistent, so building up a ConcurrentDictionary<string, T> would enhance long term performance significantly.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.