C# Programming – Mapping Convention for Objects

cobject-oriented-designprogramming practices

so this is C# but it could apply to any OO language where different sets of objects exist across different layers of an application.

We have been trying to come up with a convention within the team for where to put the code when mapping objects in one layer to objects in another layer. For example; mapping a Data Transfer Object to a Service Object that is used by a WCF service, or something of the like. I have the following methods that I have seen being used and am trying to decide which would be preferred by someone new looking at the code, and which of these fits best with the natural C# idioms.

These examples use AutoMapper to map an object Foo to an object Bar, but it applies to any mapping framework, or just manually creating Bar from Foo with an object initialiser. Both these objects represent the same data, but they are in different assemblies:

1) Constructor on Bar

public class Bar
{
    public Bar(Foo foo)
    {
        Mapper.Map(foo, this);
    }
}

2) Factory method on Bar

public class Bar
{
    public static Bar CreateFrom(Foo foo)
    {
        return Mapper.Map<Bar>(foo);
    }
}

3) Method on Foo to return Bar

public class Foo
{
    public Bar GetBar()
    {
        return Mapper.Map<Bar>(this);
    }
}

4) Explicit type conversion operator on Foo so it can be casted to Bar

public class Foo
{
    public static explicit operator Bar(Foo foo)
    {
        return Mapper.Map<Bar>(foo);
    }
}

5) Some implementation of the factory pattern

public class BarFactory : IFactory<Bar>
{
    public Bar Create(Foo foo)
    {
        return Mapper.Map<Bar>(foo);
    }
}

6) Just doing it in the piece code you need it in

    public void SomeMethod()
    {
        Foo foo = fooRepository.GetFoo();

        //I need it to be bar now...
        Bar bar = Mapper.Map<Bar>(foo);

    }

Disclaimer: I wish I hadn't used AutoMapper in this example. Just imagine "AutoMapper" here reads "IMappingProvider" or "IObjectConverter" or something

Best Answer

In all cases, I'd prefer #5. In the 1-2-3-4 sample of code, I think that the domain object doesn't have to know DTO objects related to him.

Let's say you have

public class User
{
    ... some properties ...
} 

public class UserThumbnail
{
    ... some properties ...
} 

A Domain Model object (User) doesn't have to know that a DTO object (UserThumbnail) is using User's properties, because it adds coupling between these classes, and the responsibility of creating the DTO object (UserThumbnail) is added to Domain object (User).

So if the use cases of your business doesn't specify that a User should be able to create a UserThumbnail, then I think that you should not do it. That's why classes like Factory should be used in this case: because DTO objects doesn't pollute domain objects. If a factory is used in that case, the domain object doesn't even know that DTO object exists.

For the #6, if you'd ever change AutoMapper to another mapping tool, then you'd have to search in your code. If you used a Factory, you know that all AutoMapper calls are there.

Mapper.Map is doing 2 things : Create instance and map properties. Factory Pattern is the solution if you want to isolate object creation code.

Related Topic