2

I've been using AutoMapper to map between an interface and a concrete implementation of that interface. I assumed that if the type that I passed in to AutoMapper's Map<TDestination> method was the same as the return type, then the original object would be returned (as a sort of short-circuiting operation). My assumption was wrong: indeed, after looking I noticed the documentation for that method explicitly states:

Execute a mapping from the source object to a new destination object. The source type is inferred from the source object. (bold emphasis mine)

I knocked-up this quick console app just to verify:

using System;
using AutoMapper;

namespace ConsoleApplication
{
    class Program
    {
        interface IFoo
        {
            string Bar { get; }
        }

        class Foo : IFoo
        {
            public string Bar { get; set; }
        }

        static void Main(string[] args)
        {
            Mapper.CreateMap<IFoo, Foo>();
            IFoo a = new Foo { Bar = "baz" };
            Foo b = Mapper.Map<Foo>(a);
            Console.WriteLine(Object.ReferenceEquals(a, b));  // false
        }
    }
}

Now that I know about this behaviour I can optimize around it for my particular use-case, but I was wondering if there is an alternate way of using AutoMapper whereby it will "short-circuit" in the way described above (ie. give me back the original object if the type is the same as the target type that I want)?

Steven Rands
  • 5,160
  • 3
  • 27
  • 56

1 Answers1

5

You can use Mapper.Map<TSource,TDestination>(source, destination) overload.

 Foo b = new Foo();
 Mapper.Map<IFoo,Foo>(a,b);

AutoMapper will use b and not build a new object. Overall you can use a wrapper around Mapper.Map, this alternative way can be better (not tested):

public class MyMapper
{

        public static TDestination Map<TDestination>(object source) where TDestination : class
        {
            if(source is TDestination)
            {
                return (TDestination) source; //short-circuit here
            }

            return Mapper.Map<TDestination>(source);
        }


        public static TDestination Map<TSource, TDestination>(TSource source, TDestination destination)
        {
            return Mapper.Map<TSource, TDestination>(source, destination);
        }
}
Mr Rivero
  • 1,248
  • 7
  • 17
  • 1
    Instead of `typeof(TDestination).IsAssignableFrom == source.GetType()` I would do the less strict `source is TDestination`. Your method would not work for interfaces, the `==` would return false. – Scott Chamberlain Apr 17 '15 at 16:28
  • Thank you Scott. I updated the samples to reflect your amazing suggest. – Mr Rivero Apr 17 '15 at 16:30
  • Another suggestion, if you use `is` you should do a direct cast like your first example, don't also use `as` like in the second example. There is no need for the extra logic the `as` will add if the cast fails because you already know the `as` will succeed from the `is` check. – Scott Chamberlain Apr 17 '15 at 16:32
  • I tried that, but I got compiler error. So I use 'as' operator. – Mr Rivero Apr 17 '15 at 16:33
  • Ah, I just checked what `Mapper.Map(source, destination);` does, your code does not copy the behavior. It needs to merge the records from source in to destination. I don't think you will be able to shortcut that method. – Scott Chamberlain Apr 17 '15 at 16:36
  • You're right, I'm only shortcut Map(source) method. I'll remove from code the if clause only because MyMapper is a wrapper around Mapper class. – Mr Rivero Apr 17 '15 at 17:00
  • @KellermanRivero Thanks for the answer, but `Mapper.Map(source, destination)` does not short-circuit and return the source object if it is the same type as the destination. Your custom `MyMapper.Map` method with the short-circuiting type check in it might be the way to go though. I've upvoted but I'll leave it a little longer before marking as the accepted answer, just in case anyone else has other suggestions. – Steven Rands Apr 20 '15 at 08:42
  • @StevenRands the Map is explicit overload of method Map to control de object creation, trying to short-circuit it violates the original purpose of these overload. – Mr Rivero Apr 20 '15 at 14:22
  • @KellermanRivero Yes, I appreciate that. My original question was whether the behaviour of the `Mapper.Map(object source)` method could be short-circuited, perhaps I should have made that clearer. – Steven Rands Apr 21 '15 at 08:12