You could use reflection OR you could keep some type safety and use something called the 'Curiously recurring template pattern'. It uses generics, if you aren't familiar with that concept, I would do some reading up as they are very powerful, useful and prevalent in the .Net Eco system. Any way, here is what I would do
public abstract class Animal<T>
where T : Animal<T>
{
public string Name {get; private set;}
public Animal(string name)
{
Name = name;
}
public abstract T Reproduce();
public static T Reproduce(T animalToReproduce)
{
return animalToReproduce.Reproduce();
}
}
public class Lion : Animal<Lion>
{
public Lion(string name)
: base (name)
{
}
public override Lion Reproduce()
{
return new Lion(RandomName());
}
}
Then you can just call Animal.Reproduce(yourAnimalInstance)
this will return an object of the correct type. For example
Lion myLion = GetALionFromSomewhere();
Lion babyLion = Animal.Reproduce(myLion);
That will compile and you've got all the goodness of type safety