コード例 #1
0
        public TN Map <T, TN>(T src, TN dest = default(TN))
        {
            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).GetInterfaces()
                .FirstOrDefault(t => t.IsGenericType && t.GetGenericTypeDefinition() == GenericEnumerableType) ??
                (typeof(T).IsGenericType &&
                 typeof(T).GetInterfaces().Any(t => t == typeof(IEnumerable)) ? typeof(T)
                        : null);

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

            if (tCol == null || tnCol == null)
            {
                throw new MapNotImplementedException(
                          string.Format("There is no mapping has bee found. Source Type: {0}, Destination Type: {1}",
                                        srcType.FullName, destType.FullName));
            }

            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);
        }
コード例 #2
0
        private object MapNonGenericInternal(Type srcType, Type dstType, object src, object dest = null)
        {
            var cacheKey = CalculateCacheKey(srcType, dstType);

            if (CustomMappers.ContainsKey(cacheKey))
            {
                var customTypeMapper = CustomMappers[cacheKey];

                var typeMapper = customTypeMapper();

                if (!_customTypeMapperCache.ContainsKey(cacheKey))
                {
                    CompileNonGenericCustomTypeMapper(srcType, dstType, typeMapper, cacheKey);
                }
                return(_customTypeMapperCache[cacheKey](src, dest));
            }

            var mappingService = dest == null ? SourceService : DestinationService;

            if (mappingService.TypeMappers.ContainsKey(cacheKey))
            {
                if (src == null)
                {
                    return(null);
                }

                var mapper            = mappingService.TypeMappers[cacheKey];
                var nonGenericMapFunc = mapper.GetNonGenericMapFunc();

                return(nonGenericMapFunc(src, dest));
            }

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

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

            if (tCol != null && tnCol != null)
            {
                CompileNonGenericCollectionMapping(srcType, dstType);
                // todo: make same signature in both compiled funcs with destination
                var result = (dest == null
                    ? _mappingServices.First(m => !m.DestinationSupport).MapCollection(cacheKey).DynamicInvoke(src)
                    : _mappingServices.First(m => m.DestinationSupport).MapCollection(cacheKey).DynamicInvoke(src, dest));
                return(result);
            }
            throw new MapNotImplementedException(
                      string.Format("There is no mapping has bee found. Source Type: {0}, Destination Type: {1}", srcType.FullName,
                                    dstType.FullName));
        }
コード例 #3
0
        public void RegisterCustom <T, TN, TMapper>() where TMapper : ICustomTypeMapper <T, TN>
        {
            lock (_lock)
            {
                var src      = typeof(T);
                var dest     = typeof(TN);
                var cacheKey = CalculateCacheKey(src, dest);

                if (CustomMappers.ContainsKey(cacheKey))
                {
                    throw new InvalidOperationException(
                              $"Mapping from {src.FullName} to {dest.FullName} is already registered");
                }

                var newExpression = Expression.New(typeof(TMapper));
                var newLambda     = Expression.Lambda <Func <ICustomTypeMapper <T, TN> > >(newExpression);
                var compile       = newLambda.Compile();
                CustomMappers[cacheKey] = compile;
            }
        }
コード例 #4
0
        public void RegisterCustom <T, TN>(Func <T, TN> mapFunc)
        {
            lock (_lock)
            {
                var src      = typeof(T);
                var dest     = typeof(TN);
                var cacheKey = CalculateCacheKey(src, dest);

                if (CustomMappers.ContainsKey(cacheKey))
                {
                    throw new InvalidOperationException(
                              $"Mapping from {src.FullName} to {dest.FullName} is already registered");
                }

                var delegateMapperType = typeof(DelegateCustomTypeMapper <,>).MakeGenericType(src, dest);
                var newExpression      =
                    Expression.New(
                        delegateMapperType.GetInfo().GetConstructor(new Type[] { typeof(Func <,>).MakeGenericType(src, dest) }),
                        Expression.Constant(mapFunc));
                var newLambda = Expression.Lambda <Func <ICustomTypeMapper <T, TN> > >(newExpression);
                var compile   = newLambda.Compile();
                CustomMappers.Add(cacheKey, compile);
            }
        }
コード例 #5
0
        private object MapNonGenericInternal(Type srcType, Type dstType, object src, object dest = null, bool dynamicTrial = false)
        {
            if (src == null)
            {
                return(null);
            }

            var cacheKey = CalculateCacheKey(srcType, dstType);

            if (CustomMappers.ContainsKey(cacheKey))
            {
                var customTypeMapper = CustomMappers[cacheKey];
                var typeMapper       = customTypeMapper();
                if (!_customTypeMapperCache.ContainsKey(cacheKey))
                {
                    CompileNonGenericCustomTypeMapper(srcType, dstType, typeMapper, cacheKey);
                }
                return(_customTypeMapperCache[cacheKey](src, dest));
            }

            ITypeMapper mapper        = null;
            var         actualSrcType = src.GetType();

            if (srcType != actualSrcType && actualSrcType.GetInfo().IsAssignableFrom(srcType))
            {
                throw new InvalidCastException($"Your source object instance type '{actualSrcType.FullName}' is not assignable from source type you specified '{srcType}'.");
            }

            var srcHash = actualSrcType.GetHashCode();

            if (dest != null)
            {
                var actualDstType = dest.GetType();
                if (dstType != actualDstType && actualDstType.GetInfo().IsAssignableFrom(dstType))
                {
                    throw new InvalidCastException($"Your destination object instance type '{actualSrcType.FullName}' is not assignable from destination type you specified '{srcType}'.");
                }

                if (CustomMappingsBySource.ContainsKey(srcHash))
                {
                    var mappings = CustomMappingsBySource[srcHash];

                    mapper =
                        mappings.Where(m => DestinationService.TypeMappers.ContainsKey(m))
                        .Select(m => DestinationService.TypeMappers[m])
                        .FirstOrDefault(tm => tm.DestinationType == actualDstType);
                }
            }
            else
            {
                if (CustomMappingsBySource.ContainsKey(srcHash))
                {
                    var mappings    = CustomMappingsBySource[srcHash];
                    var typeMappers =
                        mappings.Where(m => SourceService.TypeMappers.ContainsKey(m))
                        .Select(m => SourceService.TypeMappers[m])
                        .Where(m => dstType.GetInfo().IsAssignableFrom(m.DestinationType))
                        .ToList();
                    if (typeMappers.Count > 1)
                    {
                        if (typeMappers.All(tm => tm.DestinationType != dstType))
                        {
                            throw new AmbiguousMatchException(
                                      $"Source '{actualSrcType.FullName}' has more than one destination types' mappings");
                        }
                        mapper = typeMappers.FirstOrDefault(tm => tm.DestinationType == dstType);
                    }
                    else
                    {
                        mapper = typeMappers.First();
                    }
                }
            }

            var mappingService = dest == null ? SourceService : DestinationService;

            if (mapper != null)
            {
                var nonGenericMapFunc = mapper.GetNonGenericMapFunc();
                return(nonGenericMapFunc(src, dest));
            }

            if (mappingService.TypeMappers.ContainsKey(cacheKey))
            {
                mapper = mappingService.TypeMappers[cacheKey];
                var nonGenericMapFunc = mapper.GetNonGenericMapFunc();
                return(nonGenericMapFunc(src, dest));
            }

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

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

            if (tCol != null && tnCol != null)
            {
                CompileNonGenericCollectionMapping(srcType, dstType);
                // todo: make same signature in both compiled funcs with destination
                var result = (dest == null
                    ? _mappingServices.First(m => !m.DestinationSupport).MapCollection(cacheKey).DynamicInvoke(src)
                    : _mappingServices.First(m => m.DestinationSupport).MapCollection(cacheKey).DynamicInvoke(src, dest));
                return(result);
            }

            if (dynamicTrial)
            {
                throw new MapNotImplementedException(
                          $"There is no mapping has been found. Source Type: {srcType.FullName}, Destination Type: {dstType.FullName}");
            }
            dynamic source      = src;
            dynamic destination = dest;

            Register(source, destination);
            return(MapNonGenericInternal(srcType, dstType, src, dest, true));
        }