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); }
private void StoreKeyAt(int i, SourceAndTargetTypesKey typesKey, bool insert) { if (insert) { _checkedTypes.Insert(i, typesKey); return; } _checkedTypes.Add(typesKey); }
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; } } }
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)); }
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); } }
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)); }
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); }
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)); }
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); } } }
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); } }