My current task requires me to use a set of web service calls to a 3rd party vendor in order to retrieve and update information.
The objects used in these calls - namely the response from a get and the object passed to (and received from) an update - are identical except for the a prefix tacked on to the objects.
For example, a call to the get method may return an object like so (the actual structure may be a dozen levels deep and have a mix of properties/collections):
<getFooResponse>
<getFooResponsePropertyA>1</getFooResponsePropertyA>
<getFooResponsePropertyB>2</getFooResponsePropertyB>
<getFooResponsePropertyC>3</getFooResponsePropertyC>
</getFooResponse>
and a call to the update method may take an object that looks similar:
<updateFooRequest>
<updateFooRequestPropertyA>4</updateFooRequestPropertyA>
<updateFooRequestPropertyB>5</updateFooRequestPropertyB>
<updateFooRequestPropertyC>6</updateFooRequestPropertyC>
</updateFooRequest>
and return a third similar object:
<updateFooResponse>
<updateFooResponsePropertyA>4</updateFooResponsePropertyA>
<updateFooResponsePropertyB>5</updateFooResponsePropertyB>
<updateFooResponsePropertyC>6</updateFooResponsePropertyC>
</updateFooResponse>
Using C#, service references are easily added to my project and the concretions of the classes needed to call the API or parse a response are generated for me.
My problem lies in the fact that 3 classes are automatically generated with a nearly identical structure.
Thus I have (automatically generated):
- get Foo Response
- update Foo Request
- update Foo Response
the only difference being the prefix/suffix.
I really only care about the Foo object (as it's ~identical in all 3 scenarios).
It's a quite common scenario to do the following
- get a response from the 3rd party system
- modify the response slightly
- push the modified response back up to the 3rd party system (after converting it from a getFooResponse to an updateFooRequest)
The problem lies in the sheer amount of code necessary to map from one version of the object to another. I realize I can do this with reflection, but it's not as clear as I'd like and I'm not sure how maintainable it is for one who comes after me.
Do I have any options other than writing code that hard-codes mappings between different flavors of the objects?
1 Answer 1
Assuming that you're deserializing from the xml response and serializing from the objects themselves here is a model that may work for you.
public abstract class FooMessage
{
[XmlIgnore]
string A { get; set; }
[XmlIgnore]
string B { get; set; }
[XmlIgnore]
string C { get; set; }
}
public class UpdateFooRequest : FooMessage
{
public string UpdateFooRequestPropertyA { get { return this.A;} set { this.A = value;} }
public string UpdateFooRequestPropertyB { get { return this.B;} set { this.B = value;} }
public string UpdateFooRequestPropertyC { get { return this.A;} set { this.C = value;} }
}
public class UpdateFooResponse : FooMessage
{
public string UpdateFooResponsePropertyA { get { return this.A;} set { this.A = value;} }
public string UpdateFooResponsePropertyB { get { return this.B;} set { this.B = value;} }
public string UpdateFooResponsePropertyC { get { return this.A;} set { this.C = value;} }
}
// usage
var myMessage = new FooMessage{ A="TestA", B="TestB", C="TestC" };
var myUpdateMessage = myMessage as UpdateFooRequest;
if(myUpdateMessage != null)
{
var messageString = ConvertToXml(myUpdateMessage);
SendMessage(messageString);
}
This isn't much better than just doing the mapping code however doing it this way would easily allow for some code generation. I'm also assuming that you want to serialize/deserialize straight to/from the object/message themselves.
partial
keyword? If so, just add the partial to P. Roe's answer and you likely have a solution.