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

 

 

All content © 2010, Jim Zimmerman
Book
New Book
Links to me
On this page
Sponsors
Calendar
<March 2010>
SunMonTueWedThuFriSat
28123456
78910111213
14151617181920
21222324252627
28293031123
45678910
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