我们继承了一个项目,它是核心业务模型的一部分.
有一种方法采用泛型,从成员中查找与该类型匹配的项,然后返回该类型的列表.
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可以将相同的对象转换为继承层次结构中的各种类,以便针对不同的UI呈现不同地聚合总计. GetFoos可以返回20种不同类型的后代.
现有代码基本上在整个代码中复制并粘贴了一个大的switch语句.每个部分中的代码调用GetFoos及其相应的类型.
我们目前正在将其重构为一个统一区域,但正如我们正在做的那样,我们正在寻找其他方法来使用此方法.
一种想法是使用反射来传递类型,并且这很有效,直到我们意识到Invoke返回了一个对象,并且需要以某种方式将其转换为List< T>.
另一个是使用switch语句直到4.0,然后使用动态语言选项.
我们欢迎任何有关如何使用此方法的替代想法.我已将代码保留得非常简短,但如果您想了解任何其他详细信息,请询问.
更新
switch语句最初使用的是字符串,第一遍是将它移动到Presenter中,类似于:(在交换机上没有重构,只是在数据的位置).
// 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;
}
}
View实现(ASPX页面的代码隐藏)
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
}
我们的第一遍是至少使用switch语句中的Type或添加枚举.
我使用策略模式玩了但是当我到达装载工厂再次返回List并意识到我没有类型时不得不停止.
最佳答案 如果没有看到调用GetFoos()的代码就很难…如果你可以显示更多描述如何调用它的代码,我们可以建议如何重构它.
听起来解决方案是让您的调用例程也成为通用例程 – 这样它就可以通过使用根据需要指定的单个泛型类型来避免围绕20种类型的“切换”.然而,这可能是不可行的,但再次,没有代码,很难知道……
话虽这么说,你可以重构GetFoos更简单:
public List<T> GetFoos<T>()
{
return Foos.OfType<T>().ToList();
}
编辑:正如Eric Lippert所指出的,上面的代码返回任何类型的T类型,但也返回T的子类.虽然这很可能是实际需要的行为,但它与原始代码不同.如果由于某种原因这不合适,您可以使用:
public List<T> GetFoos<T>()
{
Type type = typeof(T);
return Foos.Where(item => item.GetType() == type).ToList();
}
这将与原始代码具有相同的行为.