Reputation: 19121
Edit: I just realized myself while typing in this question, that a simple solution can be achieved by using generics. I'm testing it, and will post it shortly...
Given two entity classes (e.g. with data loaded from a database):
class PersonFromDb
{
public string NameFromDb { get; }
// ... other properties follow...
}
class ChildFromDb
{
public PersonFromDb Person { get; }
public int AgeFromDb { get; }
}
...And the following to "target" classes, to which I would like to map:
class Person
{
public string Name{ get; set; }
}
class Child : Person
{
public int Age {get; set; }
}
Now say I've written a mapping method for mapping PersonFromDb
to Person
:
public Person MapPerson(PersonFromDb person){
return new Person {
Name = person.NameFromDb,
// ...
}
}
And another method for mapping Child:
public Child MapChild(ChildFromDb child){ ... }
What I'd like to do here though, is map to call MapPerson()
from within MapChild()
, to avoid having to re-map all the common properties.
I can't use MapPerson()
with Child
however, since it returns a Person
, not a Child
.
Is there any pattern to help me resolve this, so I won`t have to repeat so much of the mapping logic here?
Upvotes: 1
Views: 519
Reputation: 1204
You could rely on a mapping framework like AutoMapper to do the job.
Another solution could be to use interface instead of inheritance. Define a IPerson interface which would be implemented by Person et Child object. Then your MapPerson function could be somthing like MapPerson(IPerson target, PersonFromDb source) which would initialize the target object therefore being able to initialize Person or Child object.
Or you could use composition instead of inheritance and make the Person object an attribute of the child object.
Upvotes: 0
Reputation: 236268
You can create generic person mapper, which will create and map any person type, which has parameterless constructor:
public <TPerson> MapPerson<TPerson>(PersonFromDb dbPerson){
where TPerson: Person, new()
return new TPerson {
Name = dbPerson.NameFromDb,
// ...
}
}
Then use this generic person mapper to map child:
public Child MapChild(ChildFromDb dbChild)
{
var child = MapPerson<Child>(dbChild.Person);
child.Age = dbChild.AgeFromDb;
return child;
}
Upvotes: 1
Reputation: 19121
As mentioned in my edit, I realized while writing this question that there is a simple solution using generics:
public T MapPerson<T>(PersonFromDb person) where T : Person, new() {
return new T {
Name = person.NameFromDb,
// ...
}
}
This will allow for both of the following:
Person mappedPerson = MapPerson<Person>(instanceOfPersonFromDb);
Child mappedChild = MapPerson<Child>(instanceOfChildFromDb.Person);
I can then call the latter from MapChild()
, allowing me to map the common properties in MapPerson()
, then add the extra properties defined in Child
afterwards, in MapChild()
.
Upvotes: 1