简体   繁体   English

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

[英]How to cast from a concrete class to an interface type?

I am building a multi layered application. 我正在构建一个多层应用程序。

When i pass an object from my presentation layer to my business layer, i want to cast it to an interface type, because the business layer does not know of the concrete class from the presentation layer. 当我将一个对象从我的表示层传递到我的业务层时,我想将它转换为接口类型,因为业务层不知道表示层中的具体类。

    public ActionResult SubmitSurvey(SurveyAnswer answers)
    {

        ISurveyAnswer answer = (ISurveyAnswer)answers;

        bc.SaveSurvey(answer);

        return null;
    }

The class SurveyAnswer implements the interface ISurveyAnswer SurveyAnswer类实现了ISurveyAnswer接口

When i check the type in the business layer: 当我检查业务层中的类型时:

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

the GetType().Name method returns SurveyAnswer which is the concrete class from the presentation layer. GetType()。Name方法返回SurveyAnswer,它是表示层中的具体类。 Is it supposed to do that? 它应该这样做吗?

Casting does not change the type of the object. 转换不会更改对象的类型。 The object always remains the same as when it was created. 对象始终与创建时保持一致。 Casting simply changes the interface through which you are accessing the object. Casting只是更改了访问对象的界面。 It changes your "view" of the object, if you will. 如果愿意,它会改变对象的“视图”。 It's not a problem, though. 不过,这不是问题。 What you are doing is correct. 你在做什么是正确的。 All the UI layer cares about is the ISurveyAnswer interface, so as long as the object's concrete type implements that interface, then all is well and will work as you expect. 所有UI层关心的都是ISurveyAnswer接口,因此只要对象的具体类型实现了该接口,那么一切都很好并且将按预期工作。 The beauty of doing so it that now the UI layer may be given any kind of object (including mock objects) and it won't matter, as long as the object implements that same interface, the UI will work and won't care. 这样做的美妙之处在于,现在UI层可以被赋予任何类型的对象(包括模拟对象)并且无关紧要,只要对象实现相同的界面,UI将起作用并且不关心。 GetType will let you inspect the object to see what the actual type of the object is, but in most cases, it shouldn't matter to the UI layer. GetType将允许您检查对象以查看对象的实际类型,但在大多数情况下,它对UI层无关紧要。 As long as the provided object implements that interface and works properly, so will the UI. 只要提供的对象实现了该接口并且正常工作,UI也将如此。

When any class or method asks that an object of some type is passed to it, it should ideally always ask for the most narrow implementation or base type as is possible. 当任何类或方法要求将某种类型的对象传递给它时,理想情况下应始终要求尽可能最窄的实现或基类型。 So for instance, if you have a method that takes a list of items, it could look something like this: 例如,如果你有一个获取项目列表的方法,它可能看起来像这样:

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

However, technically, the method doesn't really need a List<> object, because all it's doing is enumerating through the items in the list. 但是,从技术上讲,该方法实际上并不需要List<>对象,因为它所做的只是枚举列表中的项目。 It's not using any of the members of the List<> type, itself, it's just using the members of the IEnumerable<> interface, which is implemented by the List<> type. 它没有使用List<>类型的任何成员本身,它只使用IEnumerable<>接口的成员,它由List<>类型实现。 Therefore, it would be better in this case to code the method like this: 因此,在这种情况下,将这样的方法编码更好:

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

Now, if inside the method, it not only needs to enumerate through the list, but also needs the total count of items in the list, then IEnumerable is not enough. 现在,如果在方法内部,它不仅需要通过列表枚举,而且还需要列表中项目的总数,那么IEnumerable是不够的。 But still, it wouldn't need the full List<> type, it just needs the ICollection<> type (which is also implemented by List<> ), like this: 但是,它仍然不需要完整的List<>类型,它只需要ICollection<>类型(也由List<> ),如下所示:

void printList(ICollection<Dog> dogs)
{
    printTotal(dogs.Count);
    foreach(Dog dog in dogs)
        printDog(dog);
}

But if the method neededs to get the index of each item, ICollection<> isn't enough--the method would need an IList<> type. 但是如果方法需要获取每个项的索引, ICollection<>是不够的 - 该方法需要IList<>类型。 For instance, this example shows how it might print the list of dogs and highlight every other one in the list: 例如,此示例显示了如何打印狗列表并突出显示列表中的所有其他狗:

void printList(IList<Dog> dogs)
{
    printTotal(dogs.Count);
    for(Dog dog in dogs)
        if (dogs.IndexOf(dog) % 2 == 0)
            printDog(dog);
        else
            printHighlightedDog(dog);
}

You'll notice that in none of these examples did I have to cast the dogs argument into a different type. 您会注意到,在这些示例中,我都不得不将dogs参数转换为其他类型。 I typed the argument appropriately for what I needed, so I just use it through that type's interface. 我根据需要适当地输入了参数,所以我只是通过该类型的界面使用它。 In all of these examples, a List<Dog> object can be passed into the printList method without casting (because List<> implements all of those interfaces so it can be cast implicitly): 在所有这些示例中, List<Dog>对象可以在不进行转换的情况下传递给printList方法(因为List <>实现了所有这些接口,因此可以隐式转换):

List<Dog> dogs = new List<Dog>();
dogs.Add(new Dog());
printList(dogs);

Keep in mind, this is a very simplistic example to illustrate a point. 请记住,这是一个非常简单的例子来说明一点。 In real world scenarios, you very often may just ask for List<> or IList<> even if you don't technically need everything they offer, for various reasons. 在现实场景中,您经常可能只是要求List<>IList<>即使您在技术上并不需要他们提供的所有内容,原因也各不相同。 You may know that the method may very likely will need IList<> functionality in the future, even though it only needs the IEnumerable<> functionality today. 您可能知道该方法将来很可能需要IList<>功能,即使它今天只需要IEnumerable<>功能。 But, the principle is a very good one to keep in mind as you decide on the types for arguments to your methods. 但是,当您决定方法的参数类型时,要记住这个原则是非常好的原则。

You almost never need to know the actual type of an object that is passed into a method. 您几乎不需要知道传递给方法的对象的实际类型。 All you really need to know is that it implements a particular interface so that you can access its functionality through that particular interface. 您真正需要知道的是它实现了一个特定的接口,以便您可以通过该特定接口访问其功能。

i want to cast it to an interface type 我想将它转换为接口类型

No need to. 没有必要。 If the concrete type implements the type, you don't need to cast it. 如果具体类型实现了类型,则不需要强制转换它。

This will work just fine: 这将工作得很好:

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

the GetType().Name method returns SurveyAnswer which is the concrete class from the presentation layer. GetType()。Name方法返回SurveyAnswer,它是表示层中的具体类。 Is it supposed to do that? 它应该这样做吗?

That's correct. 那是对的。 It will return the actual type being passed in (whatever you have cast it to). 它将返回传入的实际类型(无论你将其转换为什么)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM