Sunday, September 10, 2017

Mapping without Automapper

I've tried AutoMapper on numerous occasions and it's a great product. However, my mind seems to work a little bit different so I usually use a little different approach. I want to be able to follow my mappings so what I end up doing is to write the mappers by hand. (#bad)

I do give AutoMapper a try from time to time, but I still favour this way of doing it. It's just a personal preference!

If you haven't heard of Automapper, check it out at http://automapper.org/ before you embrace this technique! :)

The pattern I use for this is simple (and the magic lies in the simplicity of it).

Step 0 - Define the types on each side of the fence


Investigate the types you want to map. I have two ducks.

    public class BackendDuck
    {
        public int Id { getset; }
        public int BeakSize { getset; }
        public string TotallySecretDuckKey { getset; }
    }

    public class FrontEndDuck
    {
        public int Id { getset; }
        public int BeakSize { getset; }
    }

Step 1 - Create the mapper class


I create a static Mapper class that will handle my mappings.

   public static partial class Mapper
   {
   }


Why partial? Because I like to keep the option open to create another file to append to this mapper class. The file on disk could be called DuckMapper.cs. Then why isn't the class called DuckMapper.cs? Because we really don't want to check fifteen different classes to find the correct mapper. The answer is within step 2.

Step 2 - create the map methods:


Create two methods, both called Map (this is important), with the signature below.

    public static partial class Mapper
    {
        public static IEnumerable<FrontEndDuck> Map(IEnumerable<BackendDuck> source)
        {
            return null;
        }

        public static FrontEndDuck Map(BackendDuck source)
        {
            return null;
        }
    }

We always want two methods, one to Map an IEnumerable and one to map an item.

Step 3a - implement the map methods (non-linq way):


The first way of implementing the methods is by not using Linq. It's the straight forward, C# way to do it. No surprises at all.

    public static partial class Mapper
    {
        public static IEnumerable<FrontEndDuck> Map(IEnumerable<BackendDuck> source)
        {
            var result = new List<FrontEndDuck>();

            foreach(var item in source)
            {
                result.Add(Map(item));
            }

            return result;
        }

        public static FrontEndDuck Map(BackendDuck source)
        {
            return new FrontEndDuck()
            {
                Id = source.Id,
                BeakSize = source.BeakSize
            };
        }
    }

Step 3b - implement the map method using Linq


This does the same thing, but the looping part is hidden in a .Select extension method.

    public static partial class Mapper
    {
        public static IEnumerable<FrontEndDuck> Map(IEnumerable<BackendDuck> source)
        {
            return source.Select(x => Map(x));
        }

        public static FrontEndDuck Map(BackendDuck source)
        {
            return new FrontEndDuck()
            {
                Id = source.Id,
                BeakSize = source.BeakSize
            };
        }
    }

Step 4 - usage


This is how you would use the Mapper.

    public class DuckManager
    {
        public void DoStuff()
        {
            // Create a single duck
            var backendDuck = new BackendDuck() 
            { 
                Id = 1
                BeakSize = 42
                TotallySecretDuckKey = "TheKey" 
            };

            // Add the duck to a list
            var backendDucks = new List<BackendDuck>()
            {
                backendDuck
            };

            // Use the mappings - if setup correctly, 
            // all you have to remember is Mapper.Map(...)
            var item = Mapper.Map(backendDuck);
            var list = Mapper.Map(backendDucks);
        }
    }

Summary


Pros:
  • It's easy to follow debugging
  • You get all your mappings written in C# code that you can follow, nothing is hidden
  • Written correctly, just remember Mapping.Map( ) and you are set
Cons:
  • More code to write

Resources


Check out Automapper if you haven't done so. It might fit your needs better.

1 comment:

  1. Explore much more great articles on this topic at this site, my friends.

    ReplyDelete