public static CodeStatement CreateToSourceAssignmentMethod( TranslateAttribute attr, CodeVariableDeclarationStatement toSource, PropertyInfo toSourceProperty, CodeParameterDeclarationExpression fromTargetParam, Func<Type, Type, TranslateAttribute> getTypesTranslateAttributeFn) { var fromTargetProperty = attr.TargetType.GetProperty(toSourceProperty.Name); var cantReadFromTarget = fromTargetProperty.GetGetMethod() == null; if (cantReadFromTarget) { return new CodeCommentStatement(string.Format("Skipping property 'to.{0}' because 'model.{1}' is write-only", toSourceProperty.Name, fromTargetProperty.Name)); } var cantWriteToSource = toSourceProperty.GetSetMethod() == null; if (cantWriteToSource) { return new CodeCommentStatement(string.Format("Skipping property 'to.{0}' because 'to.{1}' is read-only", toSourceProperty.Name, toSourceProperty.Name)); } //to[property.Name] = this[property.Name] e.g: // to.Name = from.Name; if (fromTargetProperty.PropertyType.IsAssignableFrom(toSourceProperty.PropertyType)) { return toSource.Assign( toSource.RefProperty(toSourceProperty.Name), fromTargetParam.Name.RefArgument().RefProperty(toSourceProperty.Name)); } //to[property.Name] = from[property.PropertyType.Name].ToTarget() e.g: //to.Address = from.Address.ToTarget(); var toSourcePropertyType = toSourceProperty.PropertyType; var fromTargetPropertyType = fromTargetProperty.PropertyType; var targetAttr = getTypesTranslateAttributeFn(toSourcePropertyType, fromTargetPropertyType); var useExtensionMethods = attr is TranslateExtensionAttribute; var isTargetTranslatableAlso = targetAttr != null; if (isTargetTranslatableAlso) { var toSourceMethodName = targetAttr.GetConvertToSourceMethodName(); var method = useExtensionMethods ? fromTargetParam.RefProperty(toSourceProperty.Name).Call(toSourceMethodName) : toSourcePropertyType.Call(toSourceMethodName, fromTargetParam.RefProperty(toSourceProperty.Name)); return toSource.Assign(toSourceProperty.Name, method); } var fromSourceIsGenericList = toSourcePropertyType.IsGenericType && toSourcePropertyType.GetGenericTypeDefinition() == typeof(List<>); var toTargetIsGenericList = fromTargetPropertyType.IsGenericType && fromTargetPropertyType.GetGenericTypeDefinition() == typeof(List<>); var bothAreGenericLists = fromSourceIsGenericList && toTargetIsGenericList; if (bothAreGenericLists) { //to.PhoneNumbers = from.PhoneNumbers.ToPhoneNumbers(); var propertyListItemTypeAttr = getTypesTranslateAttributeFn(toSourcePropertyType.GetGenericArguments()[0], fromTargetPropertyType.GetGenericArguments()[0]); var sourceIsTranslatable = propertyListItemTypeAttr != null; if (sourceIsTranslatable) { var toSourcesMethodName = propertyListItemTypeAttr.GetConvertToSourcesMethodName(); var method = useExtensionMethods ? fromTargetParam.RefProperty(fromTargetProperty.Name).Call(toSourcesMethodName) : propertyListItemTypeAttr.SourceType.Call(toSourcesMethodName, fromTargetParam.RefProperty(fromTargetProperty.Name)); return toSource.RefProperty(toSourceProperty.Name).Assign(method); } } //to[property.Name] = this[property.Name].ToString() e.g: // to.Name = from.Name; if (toSourceProperty.PropertyType == typeof(string) && StringConverterUtils.CanCreateFromString(fromTargetProperty.PropertyType)) { var fromTargetPropertyRef = fromTargetParam.Name.RefArgument().RefProperty(toSourceProperty.Name); return fromTargetPropertyRef.IfIsNotNull( toSource.Assign( toSource.RefProperty(toSourceProperty.Name), fromTargetPropertyRef.Call("ToString"))); } // Converting 'System.Collections.Generic.List`1 PhoneNumbers' to 'System.Collections.Generic.List`1 PhoneNumbers' is unsupported return new CodeCommentStatement(string.Format("Converting '{0}.{1} {2}' to '{3}.{4} {5}' is unsupported" , toSourceProperty.PropertyType.Namespace, toSourceProperty.PropertyType.Name, toSourceProperty.Name , fromTargetProperty.PropertyType.Namespace, fromTargetProperty.PropertyType.Name, fromTargetProperty.Name)); }