//public class AbstractTypeMappingCrawler //{ // public IMapping GetMapping<TSource, TTarget>( TSource source, TTarget target, IMapping mapping ) // { // Type mappingSourceType = null; // Type mappingTargetType = null; // if( mapping is TypeMapping typeMapping ) // { // mappingSourceType = typeMapping.TypePair.SourceType; // mappingTargetType = typeMapping.TypePair.TargetType; // } // else if( mapping is MemberMapping memberMapping && // memberMapping.MappingResolution == MappingResolution.RESOLVED_BY_CONVENTION ) // { // var memberTypeMapping = memberMapping.MemberTypeMapping; // mappingSourceType = memberTypeMapping.TypePair.SourceType; // mappingTargetType = memberTypeMapping.TypePair.TargetType; // } // if( (mappingSourceType.IsInterface || mappingSourceType.IsAbstract) && // (mappingTargetType.IsInterface || mappingTargetType.IsAbstract) ) // { // return this.MappingConfiguration[ source.GetType(), target.GetType() ]; // } // if( mappingSourceType.IsInterface || mappingSourceType.IsAbstract ) // return this.MappingConfiguration[ source.GetType(), mappingTargetType ]; // if( mappingTargetType.IsInterface || mappingTargetType.IsAbstract ) // return this.MappingConfiguration[ mappingSourceType, target.GetType() ]; // } //} internal void Map <TSource, TTarget>(TSource source, TTarget target, ReferenceTracker referenceTracking, IMapping mapping) { //in order to manage inheritance at runtime here //we check if a mapping has been defined and if it has not //we create a specific mapping at runtime. //A new mapping is created only if no compatible mapping is already available //for concrete classes. If a mapping for the interfaces is found, it is used. //---runtime checks for abstract classes and interfaces. IMapping CheckResolveAbstractMapping(Type sourceType, Type targetType) { if ((sourceType.IsInterface || sourceType.IsAbstract) && (targetType.IsInterface || targetType.IsAbstract)) { return(this.MappingConfiguration[source.GetType(), target.GetType()]); } if (sourceType.IsInterface || sourceType.IsAbstract) { return(this.MappingConfiguration[source.GetType(), targetType]); } if (targetType.IsInterface || targetType.IsAbstract) { return(this.MappingConfiguration[sourceType, target.GetType()]); } return(mapping); }; if (mapping is TypeMapping typeMapping) { var mappingSourceType = typeMapping.TypePair.SourceType; var mappingTargetType = typeMapping.TypePair.TargetType; mapping = CheckResolveAbstractMapping(mappingSourceType, mappingTargetType); } else if (mapping is MemberMapping memberMapping) { if (memberMapping.MappingResolution == MappingResolution.RESOLVED_BY_CONVENTION) { var memberTypeMapping = memberMapping.MemberTypeMapping; var mappingSourceType = memberTypeMapping.TypePair.SourceType; var mappingTargetType = memberTypeMapping.TypePair.TargetType; mapping = CheckResolveAbstractMapping(mappingSourceType, mappingTargetType); } } else if (mapping == null) { mapping = CheckResolveAbstractMapping(typeof(TSource), typeof(TTarget)); } //---ends of runtime checks for abstract classes and interfaces #if DEBUG try { mapping.MappingFunc.Invoke(referenceTracking, source, target); } catch (Exception ex) { throw; } #else mapping.MappingFunc.Invoke(referenceTracking, source, target); #endif }