OK as others point out the code isn't great because you're locking in the code to a specific hierarchy. It can present problems debugging, and it's not nice to read, but the major point is the code that takes a task knows way too much about traversing to get some folder thing. Dollars to donuts, somebody's going to want to insert something in the middle. (all tasks are in a task list, etc)
Going out on a limb, are all of these classes just special names for the same thing? ie are they hierarchical, but each level has maybe a few extra properties?
So, from a different angle, I'm going to simplify to an enum and an interface, where the child classes delegate up the chain if they aren't the requested thing. For the sake of argument, I'm calling them folders.
enum FolderType { ActionPlan, ClientFile, Client, etc }
interface IFolder
{
IFolder FindTypeViaParent( FolderType folderType )
}
and each class that implements IFolder probably just does
IFolder FindTypeViaParent( FolderType folderType )
{
if( myFolderType == folderType )
return this;
if( parent == null )
return null;
IFolder parentIFolder = (IFolder)parent;
return parentIFolder.FindTypeViaParent(folderType)
}
A variation is to make the IFolder interface:
interface IFolder
{
FolderType FolderType { get; }
IFolder Parent { get; }
}
This allows you to externalize the traversal code. However this takes control away from the classes (maybe they have multiple parents) and exposes implementation. Good and bad.
[ramblings]
At a glance this appears to be a pretty expensive hierarchy to set up. Do I need to instantiate top-down every time? i.e. if something just needs a task, do you have to instantiate everything bottom-up to ensure all those back-pointers work? Even if it's lazy-load, do I need to walk up the hierarchy just to get the root?
Then again, is the hierarchy really a part of object identity? If it's not, perhaps you could externalize the hierarchy as an n-ary tree.
As a side-note, you may want to consider the DDD (Domain Driven Design) concept of aggregate and determine who the major players are. What is the ultimate owner object that is responsible? e.g. wheels of a car. In a design that models a car, the wheels are also objects, but they are owned by the car.
Maybe it works for you, maybe it doesn't. Like I said, this is just a shot in the dark.