Thursday, November 24, 2011

wish I understood AutoMapper better

AutoMapper is pretty cool. It spares you all of the right-hand, left-hand stuff of manually mapping properties of domain objects to view models. I wish I understood it better. We aim to use it more substantially in our app. I was asking Rafael some questions about it yesterday and he reinforced some of what I blogged of here.

  • typically Global.asax.cs references BootStrapper.cs
  • BootStrapper.cs initializes various profiles
  • typically an app will have one profile per project
  • a profile governs a particular concern (mapping POCOs to view models, mapping view models back to POCOs)
  • a profile will contain mapping rules if one cannot rely on naming convention for automapping (and one should try to do so)
    1. a formatter manages simple formatting rules
    2. a resolver requires a specific value and typically has more logic and dependencies to it

 
 

A example of what one might find in a profile:

Mapper.CreateMap<Account, AccountDetailViewModel>()

   .ForMember(x => x.AccountTypeName, y => y.MapFrom(z =>

         z.Division.AccountType.Name))

   .ForMember(x => x.DivisionName, y => y.MapFrom(z => z.Division.Name))

   .ForMember(x => x.ParentAccountName, y => y.MapFrom(z => z.ParentAccount

         != null ? z.ParentAccount.Name : string.Empty));

 
 

A example of coloring an action with an attribute: (a Foo is prepped in the action but a Bar is ultimately handed to the view at binding)

[AutoMap(typeof(Foo), typeof(Bar))]

public PartialViewResult Whatever(Guid id)

{

   var foo = FooRepository.GetById(id);

   foo.SomethingErOther = "this thing";

   return View("whatever", foo);

}

 
 

The attribute:

using System;

using System.Web.Mvc;

using AutoMapper;

namespace OurApp.Web.UI.ActionFilters

{

   [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]

   public class AutoMapAttribute : ActionFilterAttribute

   {

      private readonly Type _sourceType;

      private readonly Type _destType;

   

      public AutoMapAttribute(Type sourceType, Type destType)

      {

         _sourceType = sourceType;

         _destType = destType;

      }

   

      public override void OnActionExecuted(ActionExecutedContext filterContext)

      {

         var model = filterContext.Controller.ViewData.Model;

         var viewModel = Mapper.Map(model, _sourceType, _destType);

         filterContext.Controller.ViewData.Model = viewModel;

      }

   

      public Type SourceType

      {

         get { return _sourceType; }

      }

   

      public Type DestType

      {

         get { return _destType; }

      }

   }

}

 
 

A whiteboarding by Rafael:


At the left, an example of automapping:

var program = AutoMap.Map<SaveProgram, Program>(saveProgram);

Here we take an instance of SaveProgram called saveProgram and cast it to a Program called program.

 
 

At the right, showing how an object with a POCO getsetter may be flattened with its child into one simple view model without any getsetters that are not simple types.

No comments:

Post a Comment