IEnumerable Extension Method for AutoMapper#

I have been using AutoMapper for a few projects lately and just love its power and ease of use. My projects have become not only simpler to manage, but easier to do the right thing. What I mean by right thing, is creating ViewModels and Domain objects in my ASP.NET MVC projects. Although it seems like extra work to create multiple classes that seem to do what seems like the same thing, down the road it is a much better way to do things because of maintainability of views and domain logic not interfering. I am not going to get into the reason you would do this, but you can find out more here. Jimmy Bogard has a great article here as to why ViewModels are so important.

Sometimes when you do not want to have to create your maps ahead of time, it can be useful to use an extension method on IEnumerable which will work with IQueryable and any other Interface that implements IEnumerable .

An example is to map a complex query to a complex domain model. For instance, lets say I want to do a complicated db query using linq:

var q = from c in db.Customers
        select new { c.CompanyName, c.ContactName, Orders = (from order in db.Orders where order.CustomerID == c.CustomerID select order) };

AutoMapperHelper.TryCreateMap<Order, MyOrder>();
var a = q.ToModelList<ComplexCustomer>();

And here is the ComplexCustomer class that AutoMapper maps to:

public class ComplexCustomer
    {
        public string CompanyName { get; set; }
        public string ContactName { get; set; }
        public List<MyOrder> Orders { get; set; }
    }

Notice the extension Method: ToModelList(). This will execute the query to a list then automap it dynamically to the anonymous type or a defined type.

Here are the extension methods:

public static IList<TDestination> ToModelList<TDestination>(this IEnumerable query)
       {
           var output = new List<TDestination>();
           var sourceType = query.GetType().GetGenericArguments()[0];
           var destType = output.GetType().GetGenericArguments()[0];

           foreach (var src in query)
           {
               var mySrc = Mapper.DynamicMap(src, sourceType, destType);
               output.Add(Mapper.DynamicMap<TDestination>(mySrc));
           }

           return output;
       }
Code Snippet
  1. public static IList<TDestination> ToModelList<TDestination>(this IEnumerable query)
  2.         {
  3.             var output = new List<TDestination>();
  4.             var sourceType = query.GetType().GetGenericArguments()[0];
  5.             var destType = output.GetType().GetGenericArguments()[0];
  6.             foreach (var src in query)
  7.             {
  8.                 var mySrc = Mapper.DynamicMap(src, sourceType, destType);
  9.                 output.Add(Mapper.DynamicMap<TDestination>(mySrc));
  10.             }
  11.             return output;
  12.         \

There are two ways to use this extension, one is to tell the extension both the source and destination generic classes or just pass in the destination and it will use dynamic mapping to figure out what the source is. Notice that there also is a AutoMapperHelper class which helps to find out if the map you want is already in memory since AutoMapper stores the maps statically. We found that by not doing this it created a performance issue.

All in all, we are loving AutoMapper and I hope that others find this extension very useful. I have already used it with SubSonic 3, EF 4 and Action Filter Atrributes in an ASP.NET MVC Project.

Friday, July 10, 2009 8:38:52 AM UTC #    Comments [6]  |  Trackback

 

Saturday, July 11, 2009 7:24:47 AM UTC
The angle bracket monster came through and ate all your generic typing info. :)
Tuesday, July 28, 2009 9:03:42 PM UTC
Thanks for this Jim, brilliant idea. I'm going to use it in a new project I'm starting up.
Sunday, August 02, 2009 9:13:53 AM UTC
The angle bracket monster came through and ate all your generic typing info. :)

Yea what he said. I tried to copy and paste you code right into production and it didn't work ;)
Friday, August 21, 2009 7:55:33 AM UTC
I love the way you post.
Friday, September 04, 2009 8:46:47 AM UTC
Sorry about the angle bracket mess. Forgot to change the notification email for new comments and did not know of the error. Should be better now. Man i need a new blog. :)
Saturday, December 12, 2009 11:16:54 AM UTC
hi ,

will you please guide me how can i resolve my issue by Dynamic Map .

here is the scenario which i asked to Jimeey Bogard

he replied to use Dynamic Map ..

http://groups.google.com/group/automapper-users/browse_thread/thread/bef06472a8cf61ac


wi you please resolve my issue with exmple.. as i m stuck in My N-Tier Architecture


Thanks in Advance

Name
E-mail
(will show your gravatar icon)
Home page

Comment (Some html is allowed: a@href@title, b, blockquote@cite, i, strong, u)  

Enter the code shown (prevents robots):

 

All content © 2010, Jim Zimmerman
Book
New Book
Links to me
On this page
Sponsors
Calendar
<July 2009>
SunMonTueWedThuFriSat
2829301234
567891011
12131415161718
19202122232425
2627282930311
2345678
Archives
Tags
Blogroll OPML
Technorati
Favorite Links
Disclaimer

Powered by: newtelligence dasBlog 1.9.6264.0

The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

Send mail to the author(s) E-mail