How to implement an elegant animal farm?

Is there an elegant way (using generics and / or an activator and / or any other nice trick) to implement a factory object other than a big switch for the next scenario?

enum AnimalKind
{
    Bear,
    Fox,
    Ant,
}

abstract class Animal
{
    abstract AnimalKind Kind {get;}
    ...
    static Animal Create(AnimalKind kind) // Factory method, convert kind to animal
    {
        switch (kind)
        {
            case AnimalKind.Bear: return new Bear();
            ...
            // Update this part anytime the new AnimalKind is added
        }
    }
}

class Bear : Animal
{
    override AnimalKind Kind {get {return AnimalKind.Bear;}}
    ...
}
...

      

Unfortunately, the kind of animal - a requirement , and the desired goal is the following conversion: List<AnimalKind> => List<Animal>

. Otherwise, something like T Create<T>() where T:Animal

. Since new animals are encountered in the system, the fewer code updates the better (the ideal case is an enum and the animal class itself, nothing in the factory method).

Edit: Based on the comments below, the best answer is here !

Edit 2:

  • Since I can answer the question closed as a duplicate,
  • Since the referenced answer does not satisfy me,
  • Since there is no problem of poor performance due to the reflection of the farm animals,
  • Also for people who wanted to use "working examples" for copy / paste

I am posting my solution here. Feel free to modify and / or improve and / or simplify it:

Animal.cs:

using System;
using System.Linq;
using System.Reflection;

namespace ReflectionFactory
{
    public enum AnimalKind
    {
        None,
        Bear,
        Fox, 
        Ant,
    }

    public abstract class Animal
    {
        public const AnimalKind StaticKind = AnimalKind.None;
        public abstract AnimalKind Kind {get;}

        // That is the "trick" I was looking for: kind => Animal, no further changes
        public static Animal Create(AnimalKind kind)
        {
            var asm  = Assembly.GetExecutingAssembly();
            var type = asm.GetTypes()
                          .Where(t => t.IsSubclassOf(typeof(Animal)))
                          .FirstOrDefault(t => (AnimalKind)(t.GetField("StaticKind").GetValue(null)) == kind);

            // FIXME: Might want to check for unwanted type values (like null)

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

    public class Bear : Animal
    {
        public new const AnimalKind StaticKind = AnimalKind.Bear;
        public override AnimalKind Kind {get{return StaticKind;}}
        // ...
   }

    public class Fox : Animal
    {
        public new const AnimalKind StaticKind = AnimalKind.Fox;
        public override AnimalKind Kind {get{return StaticKind;}}
        // ...
    }

    public class Ant : Animal
    {
        public new const AnimalKind StaticKind = AnimalKind.Ant;
        public override AnimalKind Kind {get{return StaticKind;}}
        // ...
    }
}

      

Program.cs:

using System;
using System.Collections.Generic;
using System.Linq;

namespace ReflectionFactory
{
    class Program
    {
        static void Main(string[] args)
        {
            var shoppingList = new List<AnimalKind>
            {
                AnimalKind.Bear,
                AnimalKind.Bear,
                AnimalKind.Fox,
                AnimalKind.Ant,
                AnimalKind.Ant,
                AnimalKind.Ant,
            };

            var animalFarm = shoppingList.Select(Animal.Create);

            foreach (var animal in animalFarm)
            {
                Console.WriteLine(animal.Kind);
            }
        }
    }
}

      

+3
generics c # factory


source to share


No one has answered this question yet

See similar questions:

22
How to avoid switching case in the factory method of child classes

or similar:

3575
How to list a transfer?
2058
How do I get a consistent byte representation of strings in C # without manually specifying the encoding?
1877
What is a NullReferenceException and how do I fix it?
1758
How do I generate a random int?
1743
What's the best way to give a C # auto property an initial value?
1742
How to calculate a person's age in C #?
1064
How to sort list <T> by property in object
1027
How do I create a generic array in Java?
868
How do I use reflection to call a generic method?
662
Is List <Dog> a subclass of List <Animal>? Why are Java generics not implicitly polymorphic?



All Articles
Loading...
X
Show
Funny
Dev
Pics