如何从具体类转换为接口类型?

时间:2012-05-31 12:48:17

标签: c#

我正在构建一个多层应用程序。

当我将一个对象从我的表示层传递到我的业务层时,我想将它转换为接口类型,因为业务层不知道表示层中的具体类。

    public ActionResult SubmitSurvey(SurveyAnswer answers)
    {

        ISurveyAnswer answer = (ISurveyAnswer)answers;

        bc.SaveSurvey(answer);

        return null;
    }

班级SurveyAnswer实现了界面ISurveyAnswer

当我检查业务层中的类型时:

 public void SaveSurvey(ISurveyAnswer answer)
        {
            String type = answer.GetType().Name;
        }

GetType()。Name方法返回SurveyAnswer,它是表示层中的具体类。它应该这样做吗?

2 个答案:

答案 0 :(得分:9)

转换不会更改对象的类型。对象始终与创建时保持一致。 Casting只是更改了访问对象的界面。它改变了你的观点"对象,如果你愿意的话。不过,这不是问题。你在做什么是正确的。所有UI层都关注的是ISurveyAnswer接口,因此只要对象的具体类型实现了该接口,那么一切都很好并且将按预期工作。这样做的好处在于,现在UI层可以被赋予任何类型的对象(包括模拟对象)并且它不重要,只要对象实现相同的界面,UI将工作并赢得&#39关心。 GetType将允许您检查对象以查看对象的实际类型,但在大多数情况下,它对UI层不重要。只要提供的对象实现了该接口并且正常工作,UI就是如此。

当任何类或方法要求传递某种类型的对象时,理想情况下应始终要求尽可能最窄的实现或基类型。因此,例如,如果您有一个获取项目列表的方法,它可能看起来像这样:

void printList(List<Dog> dogs)
{
    foreach(Dog dog in dogs)
        printDog(dog);
}

但是,从技术上讲,该方法并不真正需要List<>个对象,因为它所做的只是枚举列表中的项目。它没有使用List<>类型的任何成员,它只是使用IEnumerable<>接口的成员,List<>接口由void printList(IEnumerable<Dog> dogs) { foreach(Dog dog in dogs) printDog(dog); } 实现类型。因此,在这种情况下,最好对这样的方法进行编码:

IEnumerable

现在,如果在方法内部,它不仅需要枚举列表,还需要列表中项目的总数,那么List<>是不够的。但是,它仍然不需要完整的ICollection<>类型,它只需要List<>类型(也由void printList(ICollection<Dog> dogs) { printTotal(dogs.Count); foreach(Dog dog in dogs) printDog(dog); } 实现),如下所示:

ICollection<>

但是如果方法需要获取每个项目的索引,IList<>还不够 - 该方法需要void printList(IList<Dog> dogs) { printTotal(dogs.Count); for(Dog dog in dogs) if (dogs.IndexOf(dog) % 2 == 0) printDog(dog); else printHighlightedDog(dog); } 类型。例如,此示例显示了如何打印狗列表并突出显示列表中的所有其他狗:

dogs

您会注意到,在这些示例中,我都不必将List<Dog>参数转换为其他类型。我根据需要适当地输入了参数,所以我只是通过该类型的界面使用它。在所有这些示例中,printList对象可以在不进行转换的情况下传递到List<Dog> dogs = new List<Dog>(); dogs.Add(new Dog()); printList(dogs); 方法(因为List&lt;&gt;实现了所有这些接口,因此可以隐式转换):

List<>

请记住,这是一个非常简单的例子来说明这一点。在现实场景中,您经常可能只是问IList<>IList<>,即使您在技术上不需要他们提供的所有内容,原因也各不相同。您可能知道该方法将来很可能需要IEnumerable<>功能,即使它今天只需要{{1}}功能。但是,当您决定方法参数的类型时,要记住这个原则是非常好的原则。

您几乎不需要知道传递给方法的对象的实际类型。您真正需要知道的是它实现了一个特定的接口,以便您可以通过该特定接口访问其功能。

答案 1 :(得分:4)

  

我想将其转换为接口类型

没必要。如果具体类型实现了类型,则不需要强制转换它。

这样可以正常工作:

public ActionResult SubmitSurvey(SurveyAnswer answers)
{
    bc.SaveSurvey(answers);
    return null;
}

  

GetType()。Name方法返回SurveyAnswer,它是表示层中的具体类。它应该这样做吗?

这是对的。它将返回传入的实际类型(无论你将它投射到哪里)。