internal static LambdaExpression GetMapInternal(Type tSource, Type tDest, bool resetCallContext, IObjectContext context = null)
        {
            var key = MapperKey.Get(tSource, tDest);
            LambdaExpression expression = null;

            if (context == null)
            {
                context = CreateContext();
            }

            GetMapCallContext callContext = null;

            if (resetCallContext || !context.TryGetContext <GetMapCallContext>(out callContext))
            {
                context.SetContext <GetMapCallContext>(callContext = new GetMapCallContext());
            }

            if (callContext.TryGet(key, out expression))
            {
                return(expression);
            }

            var mapCreator = GetMapCreator(key);
            var expBuilder = mapCreator.CreateUnexpandedMap(context);
            var exp        = expBuilder.Build();

            expression = ExpandInternal(exp, context);

            return(callContext.Set(key, expression));
        }
        /// <summary>
        /// Creates a dynamic lambda expression that maps one type to another. Use GetMap() to obtain the expression.
        /// <para />Mapping conventions:
        /// <para />* Auto-maps properties with matching names.
        /// <para />* Auto-maps second level properties prefixed with the first level property name. (i.e. dest.OrganisationName matched to source.Organisation.Name )
        /// <para />* When auto-mapping, the property types must match or there must be an existing map for them, otherwise the property will be ignored.
        /// <para />* Mapping conventions can be overriden via customMapping parameter.
        /// <para />* Expressions can be reused by calling InvokeMap() when overriding a property. (e.g. (TSource s) => new TDest(){ Property = s.AnotherProperty.InvokeMap&lt;Ta,Tb&gt;() } )
        /// </summary>
        /// <typeparam name="TSource">The source type</typeparam>
        /// <typeparam name="TDest">The destination type</typeparam>
        /// <param name="customMapping">A mapping expression which overrides the default mapping conventions for each property. <para /> (e.g. LinqMapper.CreateMap&lt;Tx,Ty&gt;((Tx x) => new Ty(){ Id = x.Id + 1 }); )</param>
        public static ILinqMapperSyntax <TSource, TDest> CreateMap <TSource, TDest>(Expression <Func <TSource, TDest> > customMapping = null)
            where TDest : class, new()
        {
            var key = MapperKey.Get(typeof(TSource), typeof(TDest));

            if (_Maps.ContainsKey(key))
            {
                throw new ApplicationException(String.Format("Linq map already exists for types [{0}; {1}]", key.TSource.FullName, key.TDest.FullName));
            }

            _Maps[key] = new ExtendedMapCreator <TSource, TDest>(customMapping);
            return(new LinqMapperSyntax <TSource, TDest>(key));
        }
        private static Expression TryCreateMappingExpression(Expression sourceExpression, Type sourceType, Type destType, bool nullCheckForClass)
        {
            var key = MapperKey.Get(sourceType, destType);

            if (_Maps.ContainsKey(key))
            {
                //Dynamically creates:
                //sourceExpression.InvokeMap<TSource, TDest>() OR sourceExpression.InvokeOptionalMap<TSource, TDest>() when sourceType is a class and null check is enabled
                var invokeMapMethodInfo = sourceType.IsClass && nullCheckForClass?
                                          invokeOptionalMapTemplate.MakeGenericMethod(key.TSource, key.TDest)
                                              : invokeMapTemplate.MakeGenericMethod(key.TSource, key.TDest);

                return(Expression.Call(invokeMapMethodInfo, sourceExpression));
            }
            else if (sourceType == destType && IsPrimitive(sourceType))
            {
                //the sourceExpression is compatible with the destination
                return(sourceExpression);
            }

            return(TryCreateMappingNullableDest(sourceExpression, sourceType, destType) ??
                   TryCreateMappingNullableSource(sourceExpression, sourceType, destType) ??
                   TryCreateMappingCollection(sourceExpression, sourceType, destType));
        }
 public CastBaseMapCreator()
 {
     _basekey = MapperKey.Get(typeof(TBaseSource), typeof(TBaseDest));
 }