从基类型列表中返回正确的后代类型

时间:2013-05-22 12:29:04

标签: c# linq inheritance

我有一个基类Foo,它带有一个属性,用于标识数据库项中的主键。 其他类来自我的基类Foo,并包含这些类的特殊性的另一个属性。每个下降的类代表数据库中的一个不同的表。

通常,当加载这些数据时,这些项目存储在List< Foo>类型的相同列表中。

当我需要使用某个项目时,我会根据主键找到它。

当这些项目具有相同的主键时,我的问题就出现了,当从下层的类中查找项目时,FooB最终会找到一个类FooA,因为这是第一个,然后执行强制转换为FooB的地方会引发一个激活。 / p>

var list = new List<Foo>();

list.Add(new FooA() { PrimaryKey = 1 });
list.Add(nwe FooB() { PrimaryKey = 1 });

public Foo FindItem(int pk)
{
    return list.First(it => it.PrimaryKey == 1);
}

在很多地方我使用这种方法根据我的需要找到我的项目。

var item = (FooB)FindItem(1);

在其他课程中:

var item = (FooA)FindItem(1);

在我的情况下,此代码用于系统中的许多位置,更改List&lt; Foo&gt;下降项目的列表是一个解决方案,但这意味着在许多地方进行更改,因为我无法在任何地方传递每个项目的类型。

我需要一个不会改变基本列表的解决方案。

3 个答案:

答案 0 :(得分:3)

您需要重写FindItem(1)方法,而不是返回Foo的一个实例,而是返回一个特殊对象,该对象将同时包含FooA个实例和PrimaryKey==1以及{ {1}} FooB的实例。

第二步是提供将此特殊对象转换为您需要的类型的强制转换操作符,以便代码PrimaryKey==1按预期工作。

以下是实现此类解决方案的完全可用的代码。主要缺点是您必须为正在使用的每个派生类型提供强制转换操作符。您也可以从var item = (FooB)FindItem(1)派生FooWrapper(在这种情况下,Foo只有一个属性会很简单,但这取决于您的实际Foo类)

Foo

答案 1 :(得分:0)

public T FindItem<T>(int pk) where T : Foo
{
    return list.OfType<T>().First(it => it.PrimaryKey == 1);
}

用法:

var item = FindItem<FooB>(1);

OfType<T>list有两个有益的影响:

  • 它将列表项过滤为T
  • 类型的项目
  • 它会返回IEnumerable<T>,因此FindItem的返回值已经正确输入,无需转换。

答案 2 :(得分:0)

在FindItem函数中使用泛型:

public T FindItem<T> (int pk) where T : Foo
{
    return list.OfType<T>().SingleOrDefault(it => it.PrimaryKey == pk);
}