private TN MapInternal <T, TN>(T src, TN dest = default(TN), bool dynamicTrial = false)
        {
            var srcType  = typeof(T);
            var destType = typeof(TN);
            var cacheKey = CalculateCacheKey(srcType, destType);

            if (CustomMappers.ContainsKey(cacheKey))
            {
                var customTypeMapper = CustomMappers[cacheKey];
                var typeMapper       = customTypeMapper() as ICustomTypeMapper <T, TN>;
                var context          = new DefaultMappingContext <T, TN> {
                    Source = src, Destination = dest
                };
                return(typeMapper.Map(context));
            }

            var mappingService = EqualityComparer <TN> .Default.Equals(dest, default(TN)) ? SourceService : DestinationService;

            if (mappingService.TypeMappers.ContainsKey(cacheKey))
            {
                if (EqualityComparer <T> .Default.Equals(src, default(T)))
                {
                    return(default(TN));
                }

                var mapper = mappingService.TypeMappers[cacheKey] as ITypeMapper <T, TN>;
                return(mapper != null
                    ? mapper.MapTo(src, dest)
                    : default(TN));
            }

            var tCol =
                typeof(T).GetInfo().GetInterfaces()
                .FirstOrDefault(t => t.GetInfo().IsGenericType&& t.GetGenericTypeDefinition() == GenericEnumerableType) ??
                (typeof(T).GetInfo().IsGenericType &&
                 typeof(T).GetInfo().GetInterfaces().Any(t => t == typeof(IEnumerable)) ? typeof(T)
                    : null);

            var tnCol = typeof(TN).GetInfo().GetInterfaces()
                        .FirstOrDefault(t => t.GetInfo().IsGenericType&& t.GetGenericTypeDefinition() == GenericEnumerableType) ??
                        (typeof(TN).GetInfo().IsGenericType&& typeof(TN).GetInfo().GetInterfaces().Any(t => t == typeof(IEnumerable)) ? typeof(TN)
                            : null);

            if ((tCol == null || tnCol == null))
            {
                if (dynamicTrial)
                {
                    throw new MapNotImplementedException(
                              $"There is no mapping has been found. Source Type: {srcType.FullName}, Destination Type: {destType.FullName}");
                }
                Register <T, TN>();
                return(MapInternal(src, dest, true));
            }

            if (EqualityComparer <TN> .Default.Equals(dest, default(TN)))
            {
                PrecompileCollection <T, TN>(CompilationTypes.Source);
            }
            else
            {
                PrecompileCollection <T, TN>();
            }

            // todo: make same signature in both compiled funcs with destination
            var result = (TN)(((EqualityComparer <TN> .Default.Equals(dest, default(TN)))
                ? SourceService.MapCollection(cacheKey).DynamicInvoke(src)
                : DestinationService.MapCollection(cacheKey).DynamicInvoke(src, dest)));

            return(result);
        }