AutoMapper feature: interfaces and dynamic mapping
In this post, I’ll highlight two features new in the 0.3 release: mapping to interfaces and dynamic mapping. Both of these come up in rather interesting scenarios.
Mapping to interface destinations
In some messaging scenarios, the message itself is not a DTO type, but rather an interface. In these cases, it’s rather annoying to create a derived type just for every interface-based message in your system. Instead, we can use AutoMapper to do the work for us. Suppose we have these source types:
public class OrderForm { public Customer Customer { get; set; } } public class Customer { public string Name { get; set; } }
These can be from a complex domain model, external system, or business objects. We now need to interface with some external system, but they’ve defined their message contracts as interfaces. It’s not completely out of the question, but I run into this from time to time. It might require some message like:
public interface ICreateOrderMessage { string CustomerName { get; set; } }
In this case, the destination type is an interface, and its member is a flattened version of our domain model. Here’s our mapping code:
Mapper.CreateMap<OrderForm, ICreateOrderMessage>(); Mapper.AssertConfigurationIsValid(); var order = new OrderForm { Customer = new Customer {Name = "Bob Smith"} }; var message = Mapper.Map<OrderForm, ICreateOrderMessage>(order); message.CustomerName.ShouldEqual("Bob Smith");
I create a type map from the source type (OrderForm) to the destination interface type. An implementation ICreateOrderMessage doesn’t exist anywhere in our system. I create the order form, and map to the message with the Mapper.Map call. At runtime, AutoMapper creates a dynamic proxy type for ICreateOrderMessage, using the default property behavior for getters and setters. Underneath the covers, I used LinFu to create the proxy type. Using this feature does not require any additional references, however, as the LinFu assembly is merged into the AutoMapper assembly.
Dynamic mapping
In most mapping scenarios, we know the type we’re mapping to at compile time. In some cases, the source type isn’t known until runtime, especially in scenarios where I’m using dynamic types or in extensibility scenarios. To support these scenarios, but still preserve the safety of configuration validation, AutoMapper 0.3 includes a way to dynamically map from a source to a destination type. No configuration is needed, just one call to AutoMapper. I’ll still try to map to the interface destination:
public interface ICreateOrderMessage { string CustomerName { get; set; } }
And instead of creating a OrderForm in the previous example, I’ll use a dynamic type:
var order = new {CustomerName = "Bob Smith"}; var message = Mapper.DynamicMap<ICreateOrderMessage>(order); message.CustomerName.ShouldEqual("Bob Smith");
The DynamicMap call creates a configuration for the type of the source object passed in to the destination type specified. If the two types have already been mapped, AutoMapper skips this step (as I can call DynamicMap multiple times for this example). To be safe, AutoMapper will validate the configuration for a dynamic map the first time executed, as it tends to give better messages than a mapping exception.
With DynamicMap, you don’t have the luxury of configuring the mapping, but at this point, you’ve also lost the benefits of a single AssertConfigurationIsValid call. In the DynamicMap side, I could lower the bar quite a bit and not do any mapping validation, but I’d rather not as its intended use is a very specific scenario. The ideal case is to configure your mappings up front, for much better testability.