1

I have this inheritance model:

public class Animal
{
}

public class Dog : Animal
{
    public static List<Action<Dog>> Augmenters = new List<Action<Dog>>();
}

public class Cat : Animal
{
    public static List<Action<Cat>> Augmenters = new List<Action<Cat>>();
}

// in another place of the code, augmenters are added and configured
public static void Main (string[] args) 
{
    Dog.Augmenters.Add(dog => 
    {
         // doing something with dog
    });        
    Cat.Augmenters.Add(cat => 
    {
         // doing something with cat
    });
}

Augmenters have a lot of static code in each Dog/Cat/etc. classes including null checking, instantiation, concurrency control, performance tuning, etc. that is exactly the same across all derived classes.

Dog augmenters should be static, because they apply to all dogs, not just one dog. So does cat augmenters, etc.

Yet they can't be migrated to Animal class, because augmenters of each derived class differs from other classes. If I move Augmenters to the Animal class, then each augmenter that should only belong to cats, will be applied to dogs too.

How do you DRY this type of boilerplate code?

I saw something similar for C++ here, it's called CRTP.

1 Answers1

3

Let me try to dry

class Program
{

    public abstract class Animal<T> where T : Animal<T>
    {
        public static List<Action<T>> Augmenters = new List<Action<T>>();
    }

    public class Dog : Animal<Dog>
    {

    }

    public class Cat : Animal<Cat>
    {

    }

    // in another place of the code, augmenters are added and configured
    public static void Main(string[] args)
    {
        Dog.Augmenters.Add(dog =>
        {
            Console.WriteLine("bark");
        });

        Cat.Augmenters.Add(cat =>
        {
            Console.WriteLine("meow");
        });

        Dog.Augmenters[0].Invoke(new Dog());
        Cat.Augmenters[0].Invoke(new Cat());
        Console.ReadLine();
    }
}

Added an abstract method and added a constraint for its type, at least you don't have to repeat the implementation of Augementers inside the concrete classes.

ChizT
  • 677
  • 3
  • 10