动态地将对象转换为正确的子类

时间:2014-03-12 17:39:01

标签: c# casting

假设我有接口IApple和实现它的类Apple。另外,我有几个扩展AppleSpartanAppleGreenApple等的类。)

现在,我有以下函数来处理将apple添加到我的数据库中:

public void CreateApple(IApple apple) 
{
    ...

    db.Apples.Add(apple);    // This will take an object of type Apple, or ANY of its sub-types
    db.SaveChanges();
}

问题是db.Apples.Add(apple);会产生以下编译时错误

Argument 1: cannot convert from 'IApple' to 'Apple'

因此,在将apple传递给Add()之前,我需要将apple转换为适当的类型。我可以通过使用if语句并根据某些属性将{{1}}转换为适当的类型来实现,但是我不希望每次添加新的子类时都要添加新的大小写

我觉得我在这里错过了一些微不足道的东西。有没有更优雅的方式来做到这一点?任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:3)

您可以将其投放到Apple。 EF会在Add方法中正确找出实际类型:

db.Apples.Add((Apple)apple);

<强>更新

正如@AntP所提到的,您可以通过更改方法签名来接受Apple而不是IApple来避免投射:

public void CreateApple(Apple apple) 
{
    ...

    db.Apples.Add(apple);

答案 1 :(得分:3)

如果CreateApple的唯一目的是将其保存到仅接受Apple的存储库,则只需更改签名:

public void CreateApple(Apple apple) 
{
    ...

    db.Apples.Add(apple);    // This will take an object of type Apple, or ANY of its sub-types
    db.SaveChanges();
}

如果在CreateApple中使用接口的原因是不依赖于实现,那么如果内部需要对{{1}进行处理,那么该模型就会被破坏}。

另一个选择是创建 Apple,只需从Apple映射:

IApple

这样,你仍然松散耦合,可以使用public void CreateApple(IApple apple) { Apple newApple = new Apple() { Color = apple.Color, Variety = apple.Variety, ... } db.Apples.Add(newApple); db.SaveChanges(); } 不同的实现,而无需更改存储库代码。