private static bool HasCompatibleSourceMember(IMemberMapperData mapperData)
        {
            if (!mapperData.SourceMember.IsEnumerable)
            {
                return(false);
            }

            var sourceElementMember = mapperData.SourceMember.GetElementMember();
            var targetElementMember = mapperData.TargetMember.GetElementMember();

            if (mapperData.CanConvert(sourceElementMember.Type, targetElementMember.Type))
            {
                return(true);
            }

            if (!mapperData.MapperContext.UserConfigurations.HasMappingFactories)
            {
                return(false);
            }

            var queryContext = new QualifiedMemberContext(
                mapperData.RuleSet,
                sourceElementMember.Type,
                targetElementMember.Type,
                sourceElementMember,
                targetElementMember,
                mapperData,
                mapperData.MapperContext);

            return(ConfiguredMappingFactory.HasMappingFactories(queryContext));
        }
        public static IDataSource Create(
            IQualifiedMember sourceMember,
            int dataSourceIndex,
            IChildMemberMappingData childMappingData)
        {
            var childMapperData = childMappingData.MapperData;

            if (!childMapperData.MapperContext.UserConfigurations.HasMappingFactories)
            {
                return(new NullDataSource(Constants.EmptyExpression));
            }

            var childObjectMappingData = ObjectMappingDataFactory.ForChild(
                sourceMember,
                childMapperData.TargetMember,
                dataSourceIndex,
                childMappingData.Parent);

            var childCreationContext = new MappingCreationContext(childObjectMappingData);

            var mapping = ConfiguredMappingFactory
                          .GetMappingOrNull(childCreationContext, out _);

            if (mapping == null)
            {
                return(new NullDataSource(Constants.EmptyExpression));
            }

            var childObjectMapperData = childObjectMappingData.MapperData;
            var sourceMemberAccess    = sourceMember.GetRelativeQualifiedAccess(childMapperData);
            var targetMemberAccess    = childMapperData.GetTargetMemberAccess();

            var mappingValues = new MappingValues(
                sourceMemberAccess,
                targetMemberAccess,
                childMapperData.ElementIndex,
                childMapperData.ElementKey,
                dataSourceIndex);

            var directAccessMapping = MappingFactory.GetDirectAccessMapping(
                mapping,
                childObjectMapperData,
                mappingValues,
                MappingDataCreationFactory.ForChild(mappingValues, childObjectMapperData));

            var returnValue = childObjectMapperData
                              .GetFinalisedReturnValue(directAccessMapping, out var returnsDefault);

            if (returnsDefault)
            {
                returnValue = Expression.Block(directAccessMapping, returnValue);
            }

            return(new AdHocDataSource(sourceMember, returnValue, childMapperData));
        }
        protected override bool TargetCannotBeMapped(IObjectMappingData mappingData, out string reason)
        {
            var mapperData = mappingData.MapperData;

            if (HasCompatibleSourceMember(mapperData))
            {
                return(base.TargetCannotBeMapped(mappingData, out reason));
            }

            if (ConfiguredMappingFactory.HasMappingFactories(mapperData))
            {
                return(base.TargetCannotBeMapped(mappingData, out reason));
            }

            if (mappingData.GetToTargetDataSources().Any(ds => ds.SourceMember.IsEnumerable))
            {
                return(base.TargetCannotBeMapped(mappingData, out reason));
            }

            reason = "No source enumerable available";
            return(true);
        }