private void AppendPropertyAssign(string sourceRefrenceName, string targetRefrenceName, string lineSplitChar, ConvertContext convertContext) { var mappingInfo = convertContext.MappingInfo; var codeBuilder = convertContext.CodeBuilder; var targetProps = mappingInfo.TargetType.GetAllMembers() .OfType <IPropertySymbol>() .Where(p => !p.IsReadOnly && p.CanBeReferencedByName && !p.IsStatic && !p.IsIndexer) .Select(p => new { p.Name, Type = p.Type }) .ToLookup(p => p.Name) .ToDictionary(p => p.Key, p => p.First().Type); var sourceProps = mappingInfo.SourceType.GetAllMembers() .OfType <IPropertySymbol>() .Where(p => p.CanBeReferencedByName && !p.IsStatic && !p.IsIndexer && !p.IsWriteOnly) .Select(p => new { p.Name, Type = p.Type }) .ToLookup(p => p.Name) .ToDictionary(p => p.Key, p => p.First().Type); foreach (var prop in targetProps) { if (mappingInfo.IgnoreTargetProperties != null && mappingInfo.IgnoreTargetProperties.Contains(prop.Key)) { continue; } if (mappingInfo.CustomerMappings != null && mappingInfo.CustomerMappings.TryGetValue(prop.Key, out var sourceExpression)) { var actualSourceExpression = sourceExpression.Replace("$", sourceRefrenceName); codeBuilder.AppendCodeLines($"{FormatRefrence(targetRefrenceName, prop.Key)} = {actualSourceExpression}{lineSplitChar}"); } else if (sourceProps.TryGetValue(prop.Key, out var sourcePropType)) { if (CanAssign(sourcePropType, prop.Value, convertContext)) { // default codeBuilder.AppendCodeLines($"{FormatRefrence(targetRefrenceName, prop.Key)} = {FormatRefrence(sourceRefrenceName, prop.Key)}{lineSplitChar}"); } else if (CanMappingCollectionProperty(sourcePropType, prop.Value, convertContext)) { // collection var newConvertContext = convertContext.Fork(sourcePropType, prop.Value); MappingCollectionProperty(newConvertContext, sourceRefrenceName, targetRefrenceName, prop.Key, lineSplitChar); } else if (CanMappingSubObjectProperty(sourcePropType, prop.Value, convertContext)) { // sub object var newConvertContext = convertContext.Fork(sourcePropType, prop.Value); MappingSubObjectProperty(newConvertContext, sourceRefrenceName, targetRefrenceName, prop.Key, lineSplitChar); } } } }
private void MappingCollectionProperty(ConvertContext convertContext, string sourceRefrenceName, string targetRefrenceName, string propertyName, string lineSplitChar) { var codeBuilder = convertContext.CodeBuilder; var targetPropertyType = convertContext.MappingInfo.TargetType; var sourcePropertyType = convertContext.MappingInfo.SourceType; var targetItemType = GetItemType(targetPropertyType); var sourceItemType = GetItemType(sourcePropertyType); var targetItemTypeText = targetItemType.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); var targetPropertyExpression = FormatRefrence(targetRefrenceName, propertyName); var sourcePropertyExpression = FormatRefrence(sourceRefrenceName, propertyName); if (sourceItemType.SafeEquals(targetItemType)) { codeBuilder.AppendCodeLines($"{targetPropertyExpression} = {sourcePropertyExpression} == null ? null : {sourcePropertyExpression}.{ToTargetMethodName()}(){lineSplitChar}"); } else if (CanAssign(sourceItemType, targetItemType, convertContext)) { codeBuilder.AppendCodeLines($"{targetPropertyExpression} = {sourcePropertyExpression} == null ? null : {sourcePropertyExpression}.Cast<{targetItemTypeText}>().{ToTargetMethodName()}(){lineSplitChar}"); } else { if (sourceItemType.IsValueType) { codeBuilder.AppendCodeLines($"{targetPropertyExpression} = {sourcePropertyExpression} == null ? null : {sourcePropertyExpression}.Select(p => new {targetItemTypeText}"); } else { codeBuilder.AppendCodeLines($"{targetPropertyExpression} = {sourcePropertyExpression} == null ? null : {sourcePropertyExpression}.Select(p => p == null ? default({targetItemTypeText}) : new {targetItemTypeText}"); } codeBuilder.BeginSegment(); var newConvertContext = convertContext.Fork(sourceItemType, targetItemType); AppendPropertyAssign("p", null, ",", newConvertContext); codeBuilder.EndSegment("})." + $"{ToTargetMethodName()}(){lineSplitChar}"); } string ToTargetMethodName() { if (targetPropertyType is IArrayTypeSymbol arrayTypeSymbol) { return(nameof(Enumerable.ToArray)); } if ((targetPropertyType as INamedTypeSymbol).ConstructUnboundGenericType() .SafeEquals(typeof(IQueryable <>))) { return(nameof(Queryable.AsQueryable)); } return(nameof(Enumerable.ToList)); } }