private static MemberAssignment BuildCustomBinding(BaseProjectionConfig config, ParameterExpression parameterExpression, PropertyInfo destinationProperty) { var expression = config.Expressions.FirstOrDefault(c => c.DestinationMemberName == destinationProperty.Name); if (expression != null) { var lambda = expression.SourceExpression as LambdaExpression; if (lambda != null) { var rightExp = new ParameterRenamer().Rename(lambda.Body, parameterExpression); return(Expression.Bind(destinationProperty, rightExp)); } } return(null); }
private static MemberAssignment BuildBinding(Expression parameterExpression, MemberInfo destinationProperty, IEnumerable <PropertyInfo> sourceProperties, BaseProjectionConfig config, Dictionary <int, int> parameterIndexs, int index, string sourcePropertyName = null) { var destPropertyType = ((PropertyInfo)destinationProperty).PropertyType; //if ((destPropertyType.IsClass && destPropertyType != typeof(string)) || (destPropertyType.IsGenericType && // destPropertyType != typeof(string) && destPropertyType.GetInterfaces().Any(t => t.Name == "IEnumerable"))) //{ int propertyHashCode = destinationProperty.GetHashCode(); if (parameterIndexs.ContainsKey(propertyHashCode)) { parameterIndexs[propertyHashCode] = parameterIndexs[propertyHashCode] + 1; } else { parameterIndexs.Add(propertyHashCode, 1); } int maxDepth = 3; if (config != null && config.MaxDepth > 0) { maxDepth = config.MaxDepth; } if (parameterIndexs[propertyHashCode] >= maxDepth) { return(null); } //} if (!string.IsNullOrEmpty(sourcePropertyName)) { parameterExpression = Expression.Property(parameterExpression, parameterExpression.Type.GetProperty(sourcePropertyName)); } var sourceProperty = sourceProperties.FirstOrDefault(src => src.Name == destinationProperty.Name); if (sourceProperty != null) { if (destPropertyType.IsClass && destPropertyType != typeof(string) && destPropertyType != sourceProperty.PropertyType) { var sProperties = sourceProperty.PropertyType.GetProperties(); var dProperties = destPropertyType.GetProperties().Where(dest => dest.CanWrite); var bindings = dProperties .Select(dProperty => BuildBinding(parameterExpression, dProperty, sProperties, config, parameterIndexs, index, destinationProperty.Name)) .Where(binding => binding != null); var newMemberExpression = Expression.MemberInit(Expression.New(destPropertyType), bindings); if (sourceProperty.PropertyType.GetCustomAttribute <ComplexTypeAttribute>() != null) { return(Expression.Bind(destinationProperty, newMemberExpression)); } var nullCheck = Expression.Equal(Expression.Property(parameterExpression, sourceProperty), Expression.Constant(null, sourceProperty.PropertyType)); var convertExp = Expression.Constant(null, destPropertyType); var conditionExpression = Expression.Condition(nullCheck, convertExp, newMemberExpression); return(Expression.Bind(destinationProperty, conditionExpression)); } if (sourceProperty.PropertyType.IsCollection() && destPropertyType.IsCollection()) { var sourceGenericArgument = sourceProperty.PropertyType.GetGenericArguments()[0]; var destinationGenericArgument = destPropertyType.GetGenericArguments()[0]; var expression = typeof(ProjectionExpression <>).MakeGenericType(sourceGenericArgument) .GetMethod("BuildExpression", BindingFlags.NonPublic | BindingFlags.Static) .MakeGenericMethod(destinationGenericArgument) .Invoke(null, new object[] { parameterIndexs, ++index }); MethodCallExpression selectExpression = Expression.Call( typeof(Enumerable), "Select", new[] { sourceGenericArgument, destinationGenericArgument }, Expression.Property(parameterExpression, sourceProperty), (Expression)expression); return(Expression.Bind(destinationProperty, selectExpression)); } Expression rightExp = Expression.Property(parameterExpression, sourceProperty); if (destPropertyType != sourceProperty.PropertyType) { rightExp = Expression.Convert(rightExp, destPropertyType); } return(Expression.Bind(destinationProperty, rightExp)); } sourceProperty = sourceProperties.FirstOrDefault(p => p.PropertyType.IsClass && p.PropertyType != typeof(string) && destinationProperty.Name.StartsWith(p.Name)); if (sourceProperty != null) { var sourceChildProperty = sourceProperty.PropertyType.GetProperties().FirstOrDefault(src => src.Name == destinationProperty.Name.Substring(sourceProperty.Name.Length).TrimStart('_')); if (sourceChildProperty != null) { Expression childExp = Expression.Property(Expression.Property(parameterExpression, sourceProperty), sourceChildProperty); Type destinationPropertyType = ((PropertyInfo)destinationProperty).PropertyType; if (sourceChildProperty.PropertyType != destinationPropertyType) { childExp = Expression.Convert(childExp, destinationPropertyType); } if (sourceProperty.PropertyType.GetCustomAttribute <ComplexTypeAttribute>() != null) { return(Expression.Bind(destinationProperty, childExp)); } var nullCheck = Expression.Equal(Expression.Property(parameterExpression, sourceProperty), Expression.Constant(null, sourceProperty.PropertyType)); Expression defaultValueExp; if (destinationPropertyType.IsValueType && !ReflectionUtils.IsNullable(destinationPropertyType)) { defaultValueExp = Expression.Constant(ActivatorExtensions.CreateInstance(destinationPropertyType)); } else { defaultValueExp = Expression.Constant(null, destinationPropertyType); } var conditionExpression = Expression.Condition(nullCheck, defaultValueExp, childExp); return(Expression.Bind(destinationProperty, conditionExpression)); } } return(null); }
private static bool HasCustomExpression(BaseProjectionConfig config, PropertyInfo pi) { return(config != null && config.Expressions.Any(c => c.DestinationMemberName == pi.Name)); }