예제 #1
0
        /// <summary>
        /// Get the right creator delegate from the cache depending on the real type of the source.
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static Func <TSource, IncludeChain, TTarget> GetCreatorByType(Tuple <Type, MapMode> key)
        {
            return(_CacheCreators.GetOrAdd(key, k =>
            {
                Type sourceType = typeof(TSource);
                Type targetType = typeof(TTarget);

                ParameterExpression paramSource = Expression.Parameter(sourceType);
                ParameterExpression paramInclude = Expression.Parameter(typeof(IncludeChain));
                Dictionary <Type, GenericAssociation> genericTypeAssociation;
                var mapInfo = MapInfo.Get(k.Item1, targetType, false, out genericTypeAssociation);
                if (mapInfo == null)
                {
                    return (source, include) => default(TTarget);
                }
                var builderExpr = MapBuilder.CreateBuilderExpression(
                    mapMode: k.Item2,
                    mapInfo: mapInfo,
                    genericTypeAssociation: genericTypeAssociation,
                    paramSource: paramSource,
                    varResult: null,
                    paramIncludeChain: paramInclude,
                    usedBuilders: null);

                var body = mapInfo.UseItemsCache ?
                           MapperCache.GetOrSet(
                    paramSource,
                    targetType,
                    paramInclude,
                    builderExpr)
                    : builderExpr;

                return Expression.Lambda <Func <TSource, IncludeChain, TTarget> >(
                    body,
                    paramSource,
                    paramInclude
                    ).Compile();
            }));
        }
예제 #2
0
        /// <summary>
        /// Get the expression that creates an instance. Call GetPolymorphedCreator(source.GetType()) if polymorphic.
        /// </summary>
        /// <param name="mapMode"></param>
        /// <param name="source"></param>
        /// <param name="targetType"></param>
        /// <param name="sourceType"></param>
        /// <param name="includeChain"></param>
        /// <param name="usedBuilders"></param>
        /// <returns></returns>
        internal static Expression GetMostConcreteExpressionCreator(MapMode mapMode, Expression source, Type targetType, Expression includeChain, List <Tuple <Type, Type> > usedBuilders)
        {
            Dictionary <Type, GenericAssociation> genericTypeAssociation;
            Expression builderExpression;

            if (MapInfo._PolymorphTypes.Contains(source.Type) || usedBuilders.Contains(Tuple.Create(source.Type, targetType)))
            {
                Expression sourceTypeExpr = MapInfo._PolymorphTypes.Contains(source.Type) ?
                                            (Expression)Expression.Call(source, typeof(object).GetMethod("GetType"))
                    : Expression.Constant(source.Type);

                builderExpression = Expression.Call(
                    Expression.Call(
                        typeof(PolymorphismManager <,>).MakeGenericType(source.Type, targetType).GetMethod(nameof(PolymorphismManager <object, object> .GetCreatorByType)),
                        Expression.Call(
                            Meta.Method(() => Tuple.Create <Type, MapMode>(null, MapMode.All)),
                            sourceTypeExpr,
                            Expression.Constant(mapMode)
                            )),
                    typeof(Func <, ,>).MakeGenericType(source.Type, typeof(IncludeChain), targetType).GetMethod("Invoke"),
                    source,
                    includeChain
                    );
            }
            else
            {
                MapInfo mapInfo = MapInfo.Get(source.Type, targetType, false, out genericTypeAssociation);
                if (mapInfo == null)
                {
                    return(targetType.IsAssignableFrom(source.Type) ? source.Convert(targetType) : null);
                }

                var actualBuilderExpression = MapBuilder.CreateBuilderExpression(
                    mapMode: mapMode,
                    mapInfo: mapInfo,
                    genericTypeAssociation: genericTypeAssociation,
                    paramSource: source,
                    varResult: null,
                    paramIncludeChain: includeChain,
                    usedBuilders: usedBuilders.ToList());
                builderExpression = mapInfo.UseItemsCache ? MapperCache.GetOrSet(source, targetType, includeChain, actualBuilderExpression) : actualBuilderExpression;
            }
            if (builderExpression == null)
            {
                return(null);
            }

            var resultVar = Expression.Variable(targetType);

            Expression result;

            if (source.Type.IsSimpleType()) // enums. Simple types have been handled earlier.
            {
                result = builderExpression;
            }
            else
            {
                result = Expression.Block(
                    new ParameterExpression[] { resultVar },
                    Expression.IfThenElse(
                        Expression.Equal(source, Expression.Default(source.Type)),
                        Expression.Assign(resultVar, Expression.Default(targetType)),
                        Expression.Assign(resultVar, builderExpression)
                        ),
                    resultVar
                    );
            }
            return(result);
        }