2012-05-31 57 views
2

我正在构建一个多层应用程序。如何从具体类转换为接口类型?

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

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()名称方法返回SurveyAnswer这与具体类。表示层。它应该这样做吗?

回答

8

铸造不会更改对象的类型。该对象始终与创建时相同。铸造只是改变你通过其访问对象的界面。如果您愿意,它会改变对象的“视图”。不过这不是问题。你在做什么是正确的。所有UI层关心的是ISurveyAnswer接口,只要对象的具体类型实现了该接口,那么一切都会很好,并且可以按照您的预期工作。这样做的好处是,现在UI层可以被赋予任何类型的对象(包括模拟对象),并且无关紧要,只要对象实现了相同的接口,UI将会工作并且不会在意。 GetType可以让你检查对象,看看对象的实际类型是什么,但是在大多数情况下,对UI层来说应该没有关系。只要提供的对象实现了该接口并且正常工作,UI也将如此。

当任何类或方法要求将某种类型的对象传递给它时,理想情况下它应始终要求尽可能最窄的实现或基类型。因此,举例来说,如果你有需要的项目列表的方法,它可能是这个样子:

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

但是,从技术上讲,该方法并不真的需要一个List<>对象,因为所有它做的是枚举列表中的项目。它不使用List<>类型的任何成员,它本身只使用接口的成员,该接口由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); 
} 

但是,如果方法neededs获得每个项目的索引,ICollection<>是不够的 - 该方法需要IList<>类型。例如,这个例子说明它如何打印狗的名单,并强调每隔1个清单:

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<>IList<>。您可能知道该方法未来可能需要IList<>功能,尽管它现在只需要功能IEnumerable<>。但是,当你决定你的方法的参数类型时,该原则是一个非常好的原则。

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

+0

当我在业务层接收对象时,对象的正确操作是什么?我应该将它映射到另一个对象,因为它来自业务层上的一个层?谢谢 – Kenci

+0

@Kenci我添加了一些例子和进一步的解释,希望能为你解决问题。 –

4

我想将它转换为一个接口类型

没有必要。如果具体类型实现该类型,则不需要投射它。

这会工作得很好。

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

对GetType()名称方法返回SurveyAnswer这是从表现层的具体类。它应该这样做吗?

这是正确的。它将返回正在传入的实际类型(无论您将其投入了哪个类型)。

相关问题