I am in a situation where I am iterating a List<Animal> and want a Handler class to handle each element according to its derived type. The way I'm doing it is weird and hard to follow. Is there a better way?
The purpose of the Handler class is to encapsulate the code for talking to the database, I don't want the animals to have any reference to it. I just want to point a hose of animals at the database and have square pegs go in square holes, and round pegs in round holes.
Thanks in advance.
abstract class Animal
{
public void update() { }
public virtual void Handle(Handler handler) { }
}
public class Dog : Animal
{
public override void Handle(Handler handler) => handler.Handle(this);
}
public class Cat : Animal
{
public override void Handle(Handler handler) => handler.Handle(this);
}
public class Handler
{
private Clinic clinic; //only the handler talks to the database
public void Handle(Animal animal) => animal.Handle(this);
public void Handle(Dog dog) { /* write dog fields to database */ }
public void Handle(Cat cat) { /* write cat fields to database */ }
}
public void main()
{
List<Animal> animals = getAnimals();
Handler handler = new Handler();
foreach(var animal in animals)
{
handler.handle(animal);
}
}
Edit: I think my question is essentially answered here: Passing different type of objects through the same method.
It seems like instead of having a sender system that he passes data to, it's like he is taking data and building a system around it. That kind of structure would incorporate design principle violations no matter what you tried to build around it.
I think the answer is to move the database write into the factory that generates the animals. This means I can't prevalidate the entire set of animals before writing, but it cleans out all the indirection and potentially removes the animal and handler classes entirely.
In C#, starting from version 7.0, you can make use of pattern matching to handle each concrete instance separately.
Alternatively you could use LINQ's
OfType<T>method to filter out instances of each concrete class and handle them that way.