コード例 #1
0
ファイル: ObjectMapper.cs プロジェクト: chaowlert/AgileMapper
        private ICache <ObjectMapperKeyBase, IObjectMapperFunc> CreateRecursionMapperFuncs()
        {
            var cache = MapperData.MapperContext.Cache.CreateNew <ObjectMapperKeyBase, IObjectMapperFunc>();

            foreach (var mappingLambdaAndKey in MapperData.RequiredMapperFuncsByKey)
            {
                var mappingLambda     = mappingLambdaAndKey.Value;
                var mappingDataObject = mappingLambda.Parameters.First();
                var mappingDataTypes  = mappingDataObject.Type.GetGenericArguments();

                var typesKey = new SourceAndTargetTypesKey(mappingDataTypes[0], mappingDataTypes[1]);

                var mapperFuncCreator = GlobalContext.Instance.Cache.GetOrAdd(typesKey, key =>
                {
                    var mapperFuncType  = typeof(RecursionMapperFunc <,>).MakeGenericType(key.SourceType, key.TargetType);
                    var lambdaParameter = Parameters.Create <LambdaExpression>("lambda");

                    var mapperFuncCreation = Expression.New(mapperFuncType.GetConstructors()[0], lambdaParameter);

                    var mapperCreationLambda = Expression.Lambda <Func <LambdaExpression, IObjectMapperFunc> >(
                        mapperFuncCreation,
                        lambdaParameter);

                    return(mapperCreationLambda.Compile());
                });

                var mapperFunc = mapperFuncCreator.Invoke(mappingLambda);

                cache.GetOrAdd(mappingLambdaAndKey.Key, k => mapperFunc);
            }

            return(cache);
        }
コード例 #2
0
        private void StoreKeyAt(int i, SourceAndTargetTypesKey typesKey, bool insert)
        {
            if (insert)
            {
                _checkedTypes.Insert(i, typesKey);
                return;
            }

            _checkedTypes.Add(typesKey);
        }
コード例 #3
0
        private void Store(SourceAndTargetTypesKey typesKey)
        {
            if (CheckedTypesCount == 0)
            {
                StoreKeyAt(0, typesKey, insert: false);
                return;
            }

            if (typesKey < _checkedTypes[0])
            {
                StoreKeyAt(0, typesKey, insert: true);
                return;
            }

            if (typesKey > _checkedTypes.Last())
            {
                StoreKeyAt(CheckedTypesCount, typesKey, insert: false);
                return;
            }

            var lowerBound = 1;
            var upperBound = CheckedTypesCount - 2;

            while (true)
            {
                if ((upperBound - lowerBound) <= 1)
                {
                    while (lowerBound <= upperBound)
                    {
                        if (_checkedTypes[lowerBound] < typesKey)
                        {
                            ++lowerBound;
                            continue;
                        }

                        break;
                    }

                    StoreKeyAt(lowerBound, typesKey, insert: true);
                    return;
                }

                var searchIndex = (lowerBound + upperBound) / 2;

                if (_checkedTypes[searchIndex] > typesKey)
                {
                    upperBound = searchIndex - 1;
                }
                else
                {
                    lowerBound = searchIndex + 1;
                }
            }
        }
コード例 #4
0
        public IObjectMappingData WithTypes(Type newSourceType, Type newTargetType)
        {
            var typesKey = new SourceAndTargetTypesKey(newSourceType, newTargetType);

            var typedWithTypesCaller = GlobalContext.Instance.Cache.GetOrAdd(typesKey, k =>
            {
                var mappingDataParameter = Parameters.Create <IObjectMappingData <TSource, TTarget> >("mappingData");
                var withTypesCall        = mappingDataParameter.GetAsCall(k.SourceType, k.TargetType);

                var withTypesLambda = Expression
                                      .Lambda <Func <IObjectMappingData <TSource, TTarget>, IObjectMappingDataUntyped> >(
                    withTypesCall,
                    mappingDataParameter);

                return(withTypesLambda.Compile());
            });

            return((IObjectMappingData)typedWithTypesCaller.Invoke(this));
        }
コード例 #5
0
ファイル: ObjectMapper.cs プロジェクト: WeiiWang/AgileMapper
        public void CacheRepeatedMappingFuncs()
        {
            // Using a for loop here because creation of a repeated mapping func can
            // cause additions to MapperData.RequiredMapperFuncKeys
            for (var i = _repeatedMappingFuncsByKey.Count; i < MapperData.RepeatedMapperFuncKeys.Count; i++)
            {
                var mapperKey = MapperData.RepeatedMapperFuncKeys[i];

                var typesKey = new SourceAndTargetTypesKey(
                    mapperKey.MapperData.SourceType,
                    mapperKey.MapperData.TargetType);

                var mapperFuncCreator = GlobalContext.Instance.Cache.GetOrAdd(typesKey, key =>
                {
                    var mapperFuncType      = typeof(RepeatedMapperFunc <,>).MakeGenericType(key.SourceType, key.TargetType);
                    var mapperDataParameter = Parameters.Create <IObjectMappingData>("mappingData");
                    var lazyLoadParameter   = Parameters.Create <bool>("lazyLoadFuncs");

                    var mapperFuncCreation = Expression.New(
                        mapperFuncType.GetPublicInstanceConstructor(typeof(IObjectMappingData), typeof(bool)),
                        mapperDataParameter,
                        lazyLoadParameter);

                    var mapperCreationLambda = Expression.Lambda <Func <IObjectMappingData, bool, IRepeatedMapperFunc> >(
                        mapperFuncCreation,
                        mapperDataParameter,
                        lazyLoadParameter);

                    return(mapperCreationLambda.Compile());
                },
                                                                              default(HashCodeComparer <SourceAndTargetTypesKey>));

                var mapperFunc = mapperFuncCreator.Invoke(
                    mapperKey.MappingData,
                    mapperKey.MappingData.MappingContext.LazyLoadRepeatMappingFuncs);

                _repeatedMappingFuncsByKey.GetOrAdd(mapperKey, k => mapperFunc);
            }
        }
コード例 #6
0
        public static IObjectMappingData ForChild(
            IQualifiedMember sourceMember,
            QualifiedMember targetMember,
            int dataSourceIndex,
            IObjectMappingData parent)
        {
            var key = new SourceAndTargetTypesKey(sourceMember.Type, targetMember.Type);

            var typedForChildCaller = GlobalContext.Instance.Cache.GetOrAdd(key, k =>
            {
                var bridgeParameter             = Expression.Parameter(typeof(IObjectMappingDataFactoryBridge), "bridge");
                var childMembersSourceParameter = Expression.Parameter(typeof(object), "childMembersSource");
                var parentParameter             = Expression.Parameter(typeof(object), "parent");

                var typedForChildMethod = bridgeParameter.Type
                                          .GetPublicInstanceMethod("ForChild")
                                          .MakeGenericMethod(k.SourceType, k.TargetType);

                var typedForChildCall = Expression.Call(
                    bridgeParameter,
                    typedForChildMethod,
                    childMembersSourceParameter,
                    parentParameter);

                var typedForChildLambda = Expression.Lambda <Func <IObjectMappingDataFactoryBridge, object, object, object> >(
                    typedForChildCall,
                    bridgeParameter,
                    childMembersSourceParameter,
                    parentParameter);

                return(typedForChildLambda.Compile());
            },
                                                                            default(HashCodeComparer <SourceAndTargetTypesKey>));

            var membersSource = new FixedMembersMembersSource(sourceMember, targetMember, dataSourceIndex);

            return((IObjectMappingData)typedForChildCaller.Invoke(_bridge, membersSource, parent));
        }
コード例 #7
0
        private bool TypesChecked(SourceAndTargetTypesKey typesKey, int startIndex)
        {
            // ReSharper disable InconsistentlySynchronizedField
            if (CheckedTypesCount == 0)
            {
                return(false);
            }

            if ((typesKey < _checkedTypes[0]) && (typesKey > _checkedTypes.Last()))
            {
                return(false);
            }

            var lowerBound = Math.Max(startIndex, 0);
            var upperBound = CheckedTypesCount - 1;

            while (lowerBound <= upperBound)
            {
                var searchIndex = (lowerBound + upperBound) / 2;

                if (_checkedTypes[searchIndex].Equals(typesKey))
                {
                    return(true);
                }

                if (_checkedTypes[searchIndex] > typesKey)
                {
                    upperBound = searchIndex - 1;
                }
                else
                {
                    lowerBound = searchIndex + 1;
                }
            }

            return(false);
        }
コード例 #8
0
        public static IObjectMappingData ForElement(IObjectMappingData parent)
        {
            var sourceElementMember = parent.MapperData.SourceMember.GetElementMember();
            var targetElementMember = parent.MapperData.TargetMember.GetElementMember();

            var key = new SourceAndTargetTypesKey(sourceElementMember.Type, targetElementMember.Type);

            var typedForElementCaller = GlobalContext.Instance.Cache.GetOrAdd(key, k =>
            {
                var bridgeParameter        = Expression.Parameter(typeof(IObjectMappingDataFactoryBridge), "bridge");
                var membersSourceParameter = Expression.Parameter(typeof(object), "membersSource");
                var parentParameter        = Expression.Parameter(typeof(object), "parent");

                var typedForElementMethod = bridgeParameter.Type
                                            .GetMethod("ForElement")
                                            .MakeGenericMethod(k.SourceType, k.TargetType);

                var typedForElementCall = Expression.Call(
                    bridgeParameter,
                    typedForElementMethod,
                    membersSourceParameter,
                    parentParameter);

                var typedForElementLambda = Expression.Lambda <Func <IObjectMappingDataFactoryBridge, object, object, object> >(
                    typedForElementCall,
                    bridgeParameter,
                    membersSourceParameter,
                    parentParameter);

                return(typedForElementLambda.Compile());
            });

            var membersSource = new FixedMembersMembersSource(sourceElementMember, targetElementMember);

            return((IObjectMappingData)typedForElementCaller.Invoke(_bridge, membersSource, parent));
        }
コード例 #9
0
        private void LookForDerivedTypePairs(ITypePair typePair)
        {
            var rootSourceType = GetRootType(typePair.SourceType);
            var rootTargetType = GetRootType(typePair.TargetType);
            var typesKey       = new SourceAndTargetTypesKey(rootSourceType, rootTargetType);

            if (TypesChecked(typesKey, 0))
            {
                return;
            }

            // ReSharper disable once InconsistentlySynchronizedField
            var currentTypeCount = CheckedTypesCount;

            lock (_lookupSync)
            {
                if ((CheckedTypesCount > currentTypeCount) && TypesChecked(typesKey, startIndex: currentTypeCount))
                {
                    return;
                }

                Store(typesKey);

                if (rootSourceType == rootTargetType)
                {
                    AddSameRootTypePairs(rootSourceType);
                    return;
                }

                if (SkipDerivedTypePairsLookup(
                        rootSourceType,
                        rootTargetType,
                        out var derivedTargetTypeNameFactory))
                {
                    return;
                }

                var derivedSourceTypes = GlobalContext.Instance.DerivedTypes.GetTypesDerivedFrom(rootSourceType);

                if (derivedSourceTypes.None())
                {
                    return;
                }

                var derivedTargetTypes = GlobalContext.Instance.DerivedTypes.GetTypesDerivedFrom(rootTargetType);

                if (derivedTargetTypes.None())
                {
                    return;
                }

                var candidatePairsData = derivedSourceTypes.ProjectToArray(derivedTargetTypeNameFactory, (dttnf, t) => new
                {
                    DerivedSourceType     = t,
                    DerivedTargetTypeName = dttnf.Invoke(t)
                });

                foreach (var candidatePairData in candidatePairsData)
                {
                    var derivedTargetType = derivedTargetTypes
                                            .FirstOrDefault(candidatePairData, (cpd, t) => t.Name == cpd.DerivedTargetTypeName);

                    if (derivedTargetType == null)
                    {
                        continue;
                    }

                    var derivedTypePair = CreatePairFor(
                        rootSourceType,
                        candidatePairData.DerivedSourceType,
                        rootTargetType,
                        derivedTargetType);

                    Add(derivedTypePair);
                }
            }
        }
コード例 #10
0
        private void LookForDerivedTypePairs(IBasicMapperData mapperData, MapperContext mapperContext)
        {
            var rootSourceType = GetRootType(mapperData.SourceType);
            var rootTargetType = GetRootType(mapperData.TargetType);
            var typesKey       = new SourceAndTargetTypesKey(rootSourceType, rootTargetType);

            lock (_lookupSync)
            {
                if (_autoCheckedTypes.Contains(typesKey))
                {
                    return;
                }

                _autoCheckedTypes.Add(typesKey);
            }

            if (mapperData.TargetMember.IsSimple)
            {
                mapperData = mapperData.Parent;
            }

            Func <Type, string> derivedTargetTypeNameFactory;

            if (SkipDerivedTypePairsLookup(
                    mapperData,
                    rootSourceType,
                    rootTargetType,
                    out derivedTargetTypeNameFactory))
            {
                return;
            }

            var derivedSourceTypes = mapperContext.DerivedTypes.GetTypesDerivedFrom(rootSourceType);

            if (derivedSourceTypes.None())
            {
                return;
            }

            var derivedTargetTypes = mapperContext.DerivedTypes.GetTypesDerivedFrom(rootTargetType);

            if (derivedTargetTypes.None())
            {
                return;
            }

            var candidatePairsData = derivedSourceTypes
                                     .Select(t => new
            {
                DerivedSourceType     = t,
                DerivedTargetTypeName = derivedTargetTypeNameFactory.Invoke(t)
            })
                                     .ToArray();

            foreach (var candidatePairData in candidatePairsData)
            {
                var derivedTargetType = derivedTargetTypes
                                        .FirstOrDefault(t => t.Name == candidatePairData.DerivedTargetTypeName);

                if (derivedTargetType == null)
                {
                    continue;
                }

                var configInfo = new MappingConfigInfo(mapperContext)
                                 .ForRuleSet(mapperData.RuleSet)
                                 .ForSourceType(rootSourceType)
                                 .ForTargetType(rootTargetType);

                var derivedTypePair = new DerivedTypePair(
                    configInfo,
                    candidatePairData.DerivedSourceType,
                    derivedTargetType);

                Add(derivedTypePair);
            }
        }