简体   繁体   中英

Consuming an API which has a two types which are the same but have different names. How can I reuse my code?

I'm consuming a web service which returns two types which are exactly the same but are called two different things (yeah, great API I know...). One type's called SearchKMQueryResponse , the other is called TopSolutionsKMQueryResponse . I am mapping the output from these types into my own model classes and have to use two methods which take different parameter types, but return the same type. The two API types inherit the object type, so I cannot pass in a base type as a parameter. They do not expose interfaces via the API so I'm screwed there too.

So is there an elegant solution to stop repeating myself in the below code? ...

EDIT: I'm using .Net v3.5 for this solution.

      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;
        }
    }

I assume SearchKMQueryResponse and TopSolutionsKMQueryResponse are generated WCF data contracts. Those are generated as partial classes, so you can write another partial for them where you apply an interface:

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

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

Now you can change your mapper to accept an interface as input:

KmSearchResponse Map(IQueryResponse response)

My gut reaction is to say "leave it as is" - you don't control the API, so there may come a day when the different classes contain different properties. If that day ever comes, you'll have to unpick the code where you've 'merged' the two together.

You have also not specified whether the types of the properties within each of the API's response classes are the same, or whether they too are separate classes using the same naming system. If they are different, then no form of base class or interface is going to help.

I would create two extra constructors for KmSearchResponse, one accepting a parameter of type SearchKMQueryResponse and the other accepting a parameter of type TopSolutionsKMQueryResponse. Each constructor can then extract out the fields it needs.

you could use the dynamic keyword, but you wont get any intellisense.

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

EDIT: Alternatively you could write a strongly typed wrapper for each class and share a base type

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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