C# 将接口传递到RESTFUL API调用

C# 将接口传递到RESTFUL API调用,c#,rest,asp.net-web-api,C#,Rest,Asp.net Web Api,最近,我有一个面试问题,其中显示的问题是传递一个参数作为其接口。现在,我一直认为你必须通过具体化,因为没有办法知道具体化哪个实例。此外,我一直认为您“可以”返回接口……但您也应该返回混凝土 Q:参数化接口是个坏主意吗? Q:返回的接口“正常”吗? Q:如果存在多个派生,您如何知道要实例化哪个派生? public interface ICustomer { string Name { get; } IEnumerable<IOrder> Orders { get; }

最近,我有一个面试问题,其中显示的问题是传递一个参数作为其接口。现在,我一直认为你必须通过具体化,因为没有办法知道具体化哪个实例。此外,我一直认为您“可以”返回接口……但您也应该返回混凝土

Q:参数化接口是个坏主意吗?
Q:返回的接口“正常”吗?
Q:如果存在多个派生,您如何知道要实例化哪个派生?

public interface ICustomer
{
    string Name { get; }
    IEnumerable<IOrder> Orders { get; }
}

public interface IOrder
{
    IEnumerable<IOrderItem> OrderItems { get; }
}

public interface IOrderItem
{
    IEnumerable<IProduct> Products { get; }
}

public interface IProduct
{
    string Name { get; }
}

public class CustomersController : ApiController
{
    // I was always told Customer & OrderItem should be a concretes
    public IEnumerable<IOrderItem> ListOrderItems(ICustomer customer)
    {
        // Return All OrderItems for all orders
        return customer.Orders.SelectMany(o => o.OrderItems);
    }
}
更新-使其更加清晰
很抱歉澄清

如果我将其发送到服务器:
-它如何知道实例化哪个派生?(这应该失败……对吗?)

与,如果我将此发送到服务器:
-它如何知道实例化哪个派生?
-具体类型是否遵循?(我从未真正检查过)

代码示例:

public interface ICustomer
{
    string Name { get; }
    IEnumerable<IOrder> Orders { get; }
}

public interface IOrder
{
    IEnumerable<IOrderItem> OrderItems { get; }
}

public interface IOrderItem
{
    IEnumerable<IProduct> Products { get; }
}

public interface IProduct
{
    string Name { get; }
}

public class CustomersController : ApiController
{
    // I was always told Customer & OrderItem should be a concretes
    public IEnumerable<IOrderItem> ListOrderItems(ICustomer customer)
    {
        // Return All OrderItems for all orders
        return customer.Orders.SelectMany(o => o.OrderItems);
    }
}
公共接口ICustomer
{
字符串名称{get;}
IEnumerable Orders{get;}
}
公共接口路由器
{
IEnumerable OrderItems{get;}
}
公共接口IORDIETEM
{
IEnumerable乘积{get;}
}
公共接口IPProduct
{
字符串名称{get;}
}
公共类CustomerController:ApicController
{
//我总是被告知客户和订单项应该是混凝土
公共IEnumerable ListOrderItems(ICustomer客户)
{
//返回所有订单的所有OrderItems
return customer.Orders.SelectMany(o=>o.OrderItems);
}
}

通过在此场景中使用接口,您可以允许更多的代码重用。任何使用
iccustomer
接口的客户都可以被传递到此方法。此外,任何使用
IOrderItem
的OrderItem都可以迭代。与仅使用
usacusters
USOrderItem
相比,这为您提供了更多使用此方法的可能,这将把您锁定在这些具体类型中。通过使用Interfaces,您可以传递任何客户并遍历返回的OrderItem

回答你的问题

Q:参数化接口是个坏主意吗?

不,在你的场景中,这绝对不是一个坏主意

Q:返回接口是否“正常”?

是的,返回接口只是返回实现该接口的任何类型

Type objectType = myObject.GetType();
Q:如果存在多个派生,您如何知道要实例化哪个派生?

您可以收集对象的类型,它将永远不会返回您的接口

Type objectType = myObject.GetType();
然后,如果愿意,可以投射该对象


正如所发布的,这实际上在WebAPI中根本不起作用,这可能是采访问题的目的

为什么??WebAPI模型绑定器将无法确定给定的
ICCustomer
的运行时类型,因此当您实际输入该方法时,您将看到ICCustomer对象仅为null,因为它在绑定期间被跳过

我只是用一个非常简单的例子自己尝试了一下。如果我使用
iccustomer
作为我的参数类型,它总是为null。 如果我使用
客户
,一切正常


您可以通过使用自定义模型绑定将接口用作参数,顺便说一句,它不能直接“开箱即用”。关于如何做到这一点,有很多资料,我在这里不赘述。

如果有正当理由对
iccustomer
IOrder
(可能特定于
iccustomer
)进行多个派生,那么使用泛型代码就没有错,这样就不必为每个具体类型重复。我总是尽量让函数在最抽象的层上运行,以实现这一目标。
ApiController
提供(鼓励您使用)几种
IHttpActionResult
的实现。所以可以肯定地说,返回一个接口是非常好的。我很好奇面试官说的什么是对的?@PrisonerZERO,你是什么意思,
你怎么知道实例化哪个派生词?
?1)第2)号返回接口是完全正确的。3) 您需要一个自定义模型绑定器或媒体格式化程序。@Jonesopolis我的印象是Web API对通过AJAX发送的底层具体对象一无所知。它只知道……这符合ICustomer的要求。Sooooo…如果有多个…您将如何实例化ICustomer的正确派生?
object result = Convert.ChangeType(input, someOtherObject.GetType());