We have inherited a project that is a wrapper around a section of the core business model.
There is one method that takes a generic, finds items matching that type from a member and then returns a list of that type.
public List<T> GetFoos<T>()
{
List<IFoo> matches = Foos.FindAll(
f => f.GetType() == typeof(T)
);
List<T> resultList = new List<T>();
foreach (var match in matches)
{
resultList.Add((T)obj);
}
}
Foos can hold the same object cast into various classes in inheritance hierarchy to aggregate totals differently for different UI presentations. There are 20+ different types of descendants that can be returned by GetFoos.
The existing code basically has a big switch statement copied and pasted throughout the code. The code in each section calls GetFoos with its corresponding type.
We are currently refactoring that into one consolidated area, but as we are doing that we are looking at other ways to work with this method.
One thought was to use reflection to pass in the type, and that worked great until we realized the Invoke returned an object, and that it needed to be cast somehow to the List <T>.
Another was to just use the switch statement until 4.0 and then use the dynamic language options.
We welcome any alternate thoughts on how we can work with this method. I have left the code pretty brief, but if you'd like to know any additional details please just ask.
Update
The switch statement was originally using strings and the first pass was moving it into a Presenter with something like this: (No refactoring done on the switch, just where the data went).
// called on an event handler in FooPresenter
// view is the interface for the ASPX page injected into FooPresenter's constructor
// wrapper is the instance of the model wrapper that has the GetFoos method
// selectedFooName is the value of a DropDownList in the Page
// letting the user say how they want to see the animals
// its either one big group (Animal)
// or individual types (Tiger, Lion)
private void LoadFoos(string selectedFooName)
{
switch (selectedFooName)
{
case "Animal": // abstract base class for all other types
this.view.SetData(this.wrapper.GetFoos<Animal>();
case "Lion":
this.view.SetData(this.wrapper.GetFoos<Lion>();
break;
case "Tiger":
this.view.SetData(this.wrapper.GetFoos<Tiger>();
break;
case "Bear":
this.view.SetData(this.wrapper.GetFoos<Bear>();
break;
}
}
The View implementation (codebehind for an ASPX page)
public void SetData<T>(List<T> data)
{
// there is a multiview on the page that contains user controls with
// grid layouts for the different types
// there is a control for the common type of "Animal"
// and other controls for Tiger, Bear, etc
// the controls contain a 3rd party grid of pain
// and the grids' binding event handlers cast the data item
// for the row and do some stuff with it specific to that type
}
Our first pass was going to be at least using the Type in the switch statement, or adding an enum.
I played around with using the Strategy Pattern but had to stop when I got to the loading factory returning the List again and realizing I didn't have the type.