Template Method design pattern
Still, when doing such annoying work, I’m continuously striving to reduce the amount of work by trying to find smarter, faster, more concise ways for doing this tedious work (in order to finish earlier ;) ). Usually after a couple of hours common patterns/repetitions emerge as I learn the structure of the underlying XSD. Refactorings then usually help to proceed faster.
A design pattern which I found to fit nicely when doing such object mapping work is the Template Method design pattern.
A template method defines the program skeleton of an algorithm. One or more of the algorithm steps are able to be overridden by subclasses to provide their own concrete implementation. This allows differing behaviors while ensuring that the overarching algorithm is still followed.
Source: Wikipedia
In fact, the most interesting part when doing this kind of mapping work is to define an appropriate program skeleton for outlining the basic structure and here is where I used the Template Method pattern.
The data flow is from the application’s domain model to the XSD generated objects. Basically there is some input (one or potentially more domain objects) which produces the desired output (exactly one XSD generated object). These objects have then to be assembled properly before being serialized to the final XML output. Frankly, just basic serialization work.
So after a while the common repetitive work which emerged remained stable at a structure similar to
public class SomeDomainObjMapper
{
private SomeDomainObj domainObj;
private SomeOtherDomainObj otherDomainObj;
private List<LogType> logs; //for collecting log entries about problems during mappings
public SomeDomainObjMapper(SomeDomainObj domainObj, SomeOtherDomainObj otherDomainObj)
{
this.domainObj = domainObj;
this.otherDomainObj = otherDomainObj;
}
public XSDGeneratedDomainObj Map(out List<LogType> mappingLogs)
{
XSDGeneratedDomainObj convertedType = new XSDGeneratedDomainObj();
convertedType.SomeProperty = domainObj.SomeOtherProperty;
...
//more complex mappings etc..
return convertedType;
}
...
}
I guess you already identified the common pattern. There are always one or more objects from the apps domain model (which we don’t know in advance) and one XSD generated object to which data will be mapped and which will be returned. The mapping will be done by the Map(…) method which is specific to each Mapper.
So a generalized structure could look like
public abstract class BaseMapper<TItem> where TItem: new()
{
protected List<LogType> logEntries;
public BaseMapper()
{
//initialization stuff
}
//will be called from "outside", the template method
public TItem Map(out List<LogType> logs)
{
TItem convertedType = new TItem();
//call to the specific mapping method
Map();
//assign the logs to be returned
logs = logEntries;
return convertedType;
}
protected abstract void Map();
...
}
You see? This BaseMapper gives the basic structure, the skeleton. The specific mapping class will then look as follows:
public class SomeDomainObjMapper : BaseMapper<XSDGeneratedDomainObj>
{
private SomeDomainObj domainObj;
private SomeOtherDomainObj otherDomainObj;
private List<LogType> logs; //for collecting log entries about problems during mappings
public SomeDomainObjMapper(SomeDomainObj domainObj, SomeOtherDomainObj otherDomainObj)
{
this.domainObj = domainObj;
this.otherDomainObj = otherDomainObj;
}
protected void Map()
{
convertedType.SomeProperty = domainObj.SomeOtherProperty;
...
//more complex mappings etc..
}
...
}
The Map() method will now just contain the mapping and nothing else. The logic of how it is called and what is done before/after mapping resides in the template.
References: Practical example: Applying the Template Method design pattern from our NCG partner Juri Strumpflohner at the Juri Strumpflohner’s TechBlog