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 { get; set; }
public int BeakSize { get; set; }
public string TotallySecretDuckKey { get; set; }
}
public class FrontEndDuck
{
public int Id { get; set; }
public int BeakSize { get; set; }
}
{
public int Id { get; set; }
public int BeakSize { get; set; }
public string TotallySecretDuckKey { get; set; }
}
public class FrontEndDuck
{
public int Id { get; set; }
public int BeakSize { get; set; }
}
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;
}
}
{
public static IEnumerable<FrontEndDuck> Map(IEnumerable<BackendDuck> source)
{
return null;
}
public static FrontEndDuck Map(BackendDuck source)
{
return null;
}
}
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
};
}
}
{
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
};
}
}
{
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);
}
}
{
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.
No comments:
Post a Comment