private static IEnumerable<PropertyModel> CreateAdapterModel(Expression source, Expression destination, CompileArgument arg) { Type sourceType = source.Type; var destinationMembers = arg.DestinationType.GetPublicFieldsAndProperties(allowNoSetter: false); var unmappedDestinationMembers = new List<string>(); var properties = new List<PropertyModel>(); for (int i = 0; i < destinationMembers.Count; i++) { MemberInfo destinationMember = destinationMembers[i]; bool isProperty = destinationMember is PropertyInfo; if (ProcessIgnores(arg.Settings, destinationMember)) continue; if (ProcessCustomResolvers(source, destination, arg.Settings, destinationMember, properties)) continue; MemberInfo sourceMember = ReflectionUtils.GetPublicFieldOrProperty(sourceType, isProperty, destinationMember.Name); if (sourceMember != null) { var propertyModel = new PropertyModel { ConvertType = 1, Getter = sourceMember is PropertyInfo ? Expression.Property(source, (PropertyInfo)sourceMember) : Expression.Field(source, (FieldInfo)sourceMember), Setter = destinationMember is PropertyInfo ? Expression.Property(destination, (PropertyInfo) destinationMember) : Expression.Field(destination, (FieldInfo) destinationMember), SetterProperty = destinationMember, }; properties.Add(propertyModel); } else { if (FlattenMethod(source, destination, destinationMember, properties)) continue; if (FlattenClass(source, destination, destinationMember, properties, arg.MapType == MapType.Projection)) continue; if (destinationMember.HasPublicSetter()) { unmappedDestinationMembers.Add(destinationMember.Name); } } } if (arg.Context.Config.RequireDestinationMemberSource && unmappedDestinationMembers.Count > 0) { throw new ArgumentOutOfRangeException($"The following members of destination class {arg.DestinationType} do not have a corresponding source member mapped or ignored:{string.Join(",", unmappedDestinationMembers)}"); } return properties; }
private static bool FlattenMethod( Expression source, Expression destination, MemberInfo destinationMember, List<PropertyModel> properties) { var getMethod = source.Type.GetMethod(string.Concat("Get", destinationMember.Name)); if (getMethod != null) { var propertyModel = new PropertyModel { ConvertType = 2, Getter = Expression.Call(source, getMethod), Setter = destinationMember is PropertyInfo ? Expression.Property(destination, (PropertyInfo)destinationMember) : Expression.Field(destination, (FieldInfo)destinationMember), SetterProperty = destinationMember, }; properties.Add(propertyModel); return true; } return false; }
private static bool ProcessCustomResolvers( Expression source, Expression destination, TypeAdapterSettings config, MemberInfo destinationMember, List<PropertyModel> properties) { bool isAdded = false; var resolvers = config.Resolvers; if (resolvers != null && resolvers.Count > 0) { PropertyModel propertyModel = null; LambdaExpression lastCondition = null; for (int j = 0; j < resolvers.Count; j++) { var resolver = resolvers[j]; if (destinationMember.Name.Equals(resolver.MemberName)) { if (propertyModel == null) { propertyModel = new PropertyModel { ConvertType = 5, Setter = destinationMember is PropertyInfo ? Expression.Property(destination, (PropertyInfo) destinationMember) : Expression.Field(destination, (FieldInfo) destinationMember), SetterProperty = destinationMember, }; isAdded = true; } Expression invoke = resolver.Invoker.Apply(source); propertyModel.Getter = lastCondition != null ? Expression.Condition(lastCondition.Apply(source), propertyModel.Getter, invoke) : invoke; lastCondition = resolver.Condition; if (resolver.Condition == null) break; } } if (propertyModel != null) { if (lastCondition != null) propertyModel.Getter = Expression.Condition(lastCondition.Apply(source), propertyModel.Getter, Expression.Constant(propertyModel.Getter.Type.GetDefault(), propertyModel.Getter.Type)); properties.Add(propertyModel); } } return isAdded; }
private static bool FlattenClass( Expression source, Expression destination, MemberInfo destinationMember, List<PropertyModel> properties, bool isProjection) { var getter = ReflectionUtils.GetDeepFlattening(source, destinationMember.Name, isProjection); if (getter != null) { var propertyModel = new PropertyModel { ConvertType = 3, Getter = getter, Setter = destinationMember is PropertyInfo ? Expression.Property(destination, (PropertyInfo) destinationMember) : Expression.Field(destination, (FieldInfo) destinationMember), SetterProperty = destinationMember, }; properties.Add(propertyModel); return true; } return false; }