6

I have a WCF service and have just created a DTO for a business object.

My question is where to put the mapping between the two?

A) In the DTO?

public class PersonDTO
{
    [DataMember] public string Id              { get; set; }
    [DataMember] public string Name            { get; set; }

    public void CloneFrom(Person p)
    {
        Id   = p.Id;
        Name = p.Name;
    }

    public void Populate(Person p)
    {
        p.Id   = Id;
        p.Name = Name;
    }
}

or

B) In the business object?

public class Person
{
    public string Id              { get; set; }
    public string Name            { get; set; }

    public void CloneFrom(PersonDTO dto)
    {
        Id   = dto.Id;
        Name = dto.Name;
    }

    public PersonDTO GetDTO()
    {
        return new PersonDTO()
        {
            Id   = Id;
            Name = Name;
        }
    }
}

I like the separation of concerns in A (Business object has no knowledge of DTOs), but I prefer the encapsulation of B (no need to expose business object guts to DTO).

Just wondered if there was a standard way?

GazTheDestroyer
  • 20,722
  • 9
  • 70
  • 103

3 Answers3

11

i'd think this calls for a separate class, as neither the BO nor the DTO should be concerned with their transformation into another class.

I personally use the automapper library for object transformations. With simple transformations like in your example the mapping is done in a single line of code, complex transformations are also easy to set up.

If you want to map yourself, you could still use extension methods to keep the mapping implementation separated from your DTO and BO classes.

Dirk Trilsbeek
  • 5,873
  • 2
  • 25
  • 23
  • Really? If I'm going to expose my business object to allow a 3rd class to do the mapping, I might as well do it in the DTO. Creating yet another class seems pretty overkill to me. I will take a look at automapper though, thanks. – GazTheDestroyer Apr 24 '12 at 14:12
  • 4
    @GazTheDestroyer: A DTO is meant for data transfer not transform. A DTO is not suppose to be aware of its usage i.e: mappings. It transports data and it is up to the consumer to use the data for what ever purpose ie: map it to a ViewModel for example. You are free to add mappings to the DTO but in my humble opinion that means though you are miss-using the intended purpose of a DTO and as such your DTO is no longer a DTO. In our current project a repository generates entities. BL receives entities, maps them to DTO. UI layer queries BL, gets DTOs and maps them to ViewModels (as required). – Nope Apr 27 '12 at 22:33
1

I would suggest a Component Layer. It should be responsibly for communication between your business layer and your data layer. In this case, you can use it to translate your DTO objects to Business Objects.

Khan
  • 17,904
  • 5
  • 47
  • 59
  • In my experience, while NetTiers has some good qualities, actually working with it can be frustrating, see http://stackoverflow.com/questions/8220206/whither-nettiers – David Clarke Nov 17 '13 at 22:55
  • @DavidClarke The reference I had was mainly just to the definition of a component layer. The link I provided is broken, so I'll remove. :) – Khan Nov 19 '13 at 03:32
0

You're concern "no need to expose business object guts to DTO" seems bit unfounded unless there is something you are not showing in you code since you are accessing public properties, i.e. not the guts at all.

As an aside, instead of having clone methods you could implement a cast operator instead: MSDN

That way you can do something like: Person p = (Person)myPersonDTO;

Peter
  • 797
  • 11
  • 35
  • Yes, my example was very simple. In reality my business objects have private stuff that I don't really want to expose for mapping purposes. – GazTheDestroyer Apr 24 '12 at 14:09
  • 1
    If the stuff on the BO is defined private/protected then anything using it won't see it so not sure what the problem would be on that front. – Peter May 01 '12 at 14:09