【问题标题】:Consuming an API which has a two types which are the same but have different names. How can I reuse my code?使用具有两种相同但名称不同的类型的 API。如何重用我的代码?
【发布时间】:2013-12-05 20:21:33
【问题描述】:

我正在使用一个 Web 服务,它返回两种完全相同但被称为两种不同事物的类型(是的,我知道很棒的 AP​​I...)。一种称为SearchKMQueryResponse,另一种称为TopSolutionsKMQueryResponse。我将这些类型的输出映射到我自己的模型类中,并且必须使用两种采用不同参数类型但返回相同类型的方法。这两种 API 类型继承了object 类型,因此我不能将基类型作为参数传入。他们不通过 API 公开接口,所以我也搞砸了。

那么有没有一个优雅的解决方案来停止在下面的代码中重复自己? ...

编辑:我使用 .Net v3.5 来解决这个问题。

      public static KmSearchResponse Map(SearchKMQueryResponse response)
    {
        if (response == null)
        {
            return null;
        }
        else
        {
            var myResponse = new KmSearchResponse()
            {
                CountTotal = long.Parse(response.model.instance.resultlist.resultlist[0].Value),
                Message = response.message,
                Status = (MyProject.Model.StatusType)response.status,
            };

            for (var startID = 2; startID < (myResponse.CountTotal * 5); startID += 5)
            {
                myResponse.Results.Add(
                    KmSearchResponseResultsMapper.Map(
                    response.model.instance.resultlist.resultlist, startID)
                    );
            }

            myResponse.Count = myResponse.Results.Count;

            return myResponse;
        }
    }

    public static KmSearchResponse Map(TopSolutionsKMQueryResponse response)
    {
        if (response == null)
        {
            return null;
        }
        else
        {
            var myResponse = new KmSearchResponse()
            {
                CountTotal = long.Parse(response.model.instance.resultlist.resultlist[0].Value),
                Message = response.message,
                Status = (MyProject.Model.StatusType)response.status,
            };

            for (var startID = 2; startID < (myResponse.CountTotal * 5); startID += 5)
            {
                myResponse.Results.Add(
                    KmSearchResponseResultsMapper.Map(
                    response.model.instance.resultlist.resultlist, startID)
                    );
            }

            myResponse.Count = myResponse.Results.Count;

            return myResponse;
        }
    }

【问题讨论】:

  • 如果该类型非常小,您可以轻松编写包装器
  • SearchKMQueryResponse 和 TopSolutionsKMQueryResponse 是您客户端的一些自动生成的类吗?
  • 没关系,你已经得到了我脑海中的答案:CodeCaster

标签: c# .net generics types .net-3.5


【解决方案1】:

我假设 SearchKMQueryResponseTopSolutionsKMQueryResponse 是生成的 WCF 数据协定。这些是作为部分类生成的,因此您可以在应用接口的地方为它们编写另一个部分:

IQueryResponse
{
    SomeModel model { get; set; }
    SomeMessage message { get; set; }
    SomeStatus status { get; set; }
}

public partial class SearchKMQueryResponse : IQueryResponse { }
public partial class TopSolutionsKMQueryResponse : IQueryResponse { }

现在您可以更改映射器以接受接口作为输入:

KmSearchResponse Map(IQueryResponse response)

【讨论】:

  • 你让我大吃一惊,先生!我必须验证它,它就像一个魅力。
  • @CodeCaster,多么漂亮的简单和优雅的解决方案。在我让它正常工作之前,我不得不弄乱我的命名空间,但它确实如此。感谢您的回复和示例代码。
【解决方案2】:

我的直觉反应是说“保持原样”——您无法控制 API,因此可能有一天不同的类包含不同的属性。如果那一天到来,您将不得不取消选择将两者“合并”在一起的代码。

您还没有指定每个 API 响应类中的属性类型是否相同,或者它们是否也是使用相同命名系统的不同类。如果它们不同,那么任何形式的基类或接口都无济于事。

我将为 KmSearchResponse 创建两个额外的构造函数,一个接受 SearchKMQueryResponse 类型的参数,另一个接受 TopSolutionsKMQueryResponse 类型的参数。然后每个构造函数都可以提取出它需要的字段。

【讨论】:

  • 您的警告确实有道理,为此 +1。 OP 虽然声明:“完全相同的两种类型”。 :)
【解决方案3】:

你可以使用动态关键字,但你不会得到任何智能感知。

http://www.hanselman.com/blog/C4AndTheDynamicKeywordWhirlwindTourAroundNET4AndVisualStudio2010Beta1.aspx

编辑:或者,您可以为每个类编写一个强类型包装器并共享一个基类型

【讨论】:

  • 恐怕我们被 .Net v3.5 困住了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-06-10
  • 2021-01-19
  • 1970-01-01
  • 1970-01-01
  • 2011-06-01
  • 2017-01-22
相关资源
最近更新 更多