private void CreateQueryableProjection() { try { foreach (var customMember in CustomMembers) { var memberQueryableExpression = MappingService.GetMemberQueryableExpression(customMember.Key.Member.DeclaringType, customMember.Value.Type); var expression = memberQueryableExpression ?? customMember.Value; _bindingExpressions.Add(customMember.Key.Member.Name, Expression.Bind(customMember.Key.Member, expression)); } foreach (var customMember in CustomFunctionMembers) { if (_bindingExpressions.ContainsKey(customMember.Key.Member.Name)) { continue; } var memberQueryableExpression = MappingService.GetMemberQueryableExpression(customMember.Key.Member.DeclaringType, customMember.Value.Type); var expression = memberQueryableExpression ?? customMember.Value; _bindingExpressions.Add(customMember.Key.Member.Name, Expression.Bind(customMember.Key.Member, expression)); } foreach (var autoMember in AutoMembers) { if (_bindingExpressions.ContainsKey(autoMember.Value.Name)) { continue; } var source = autoMember.Key as PropertyInfo; var destination = autoMember.Value as PropertyInfo; var memberQueryableExpression = MappingService.GetMemberQueryableExpression(source.PropertyType, destination.PropertyType); var propertyOrField = Expression.PropertyOrField(SourceParameter, autoMember.Key.Name); Expression expression; if (memberQueryableExpression != null) { var lambdaExpression = memberQueryableExpression as LambdaExpression; var projectionAccessMemberVisitor = new ProjectionAccessMemberVisitor(propertyOrField.Type, propertyOrField); var clearanceExp = projectionAccessMemberVisitor.Visit(lambdaExpression.Body); expression = Expression.Condition( Expression.Equal(propertyOrField, Expression.Constant(null, propertyOrField.Type)), Expression.Constant(null, ((PropertyInfo)autoMember.Value).PropertyType), clearanceExp); } else { expression = propertyOrField; } _bindingExpressions.Add(autoMember.Value.Name, Expression.Bind(autoMember.Value, expression)); } QueryableExpression = Expression.Lambda <Func <T, TN> >( Expression.MemberInit(Expression.New(typeof(TN)), _bindingExpressions.Values), SourceParameter); } catch (Exception ex) { Debug.WriteLine(string.Format("Queryable projection is not supported for such mapping. Exception: {0}", ex)); } }
private void ProcessProjectingMember(Expression sourceExp, PropertyInfo destProp) { var memberQueryableExpression = MappingService.GetMemberQueryableExpression(sourceExp.Type, destProp.PropertyType); var tCol = sourceExp.Type.GetInterfaces() .FirstOrDefault(t => t.IsGenericType && t.GetGenericTypeDefinition() == typeof(IEnumerable <>)) ?? (sourceExp.Type.IsGenericType && sourceExp.Type.GetInterfaces().Any(t => t == typeof(IEnumerable)) ? sourceExp.Type : null); var tnCol = destProp.PropertyType.GetInterfaces() .FirstOrDefault(t => t.IsGenericType && t.GetGenericTypeDefinition() == typeof(IEnumerable <>)) ?? (destProp.PropertyType.IsGenericType && destProp.PropertyType.GetInterfaces().Any(t => t == typeof(IEnumerable)) ? destProp.PropertyType : null); if (sourceExp.Type != typeof(string) && tCol != null && tnCol != null) { var sourceGenericType = sourceExp.Type.GetGenericArguments()[0]; var destGenericType = destProp.PropertyType.IsArray ? destProp.PropertyType.GetElementType() : destProp.PropertyType.GetGenericArguments()[0]; var genericMemberQueryableExpression = MappingService.GetMemberQueryableExpression(sourceGenericType, destGenericType); MethodInfo selectMethod = null; foreach ( var p in from m in typeof(Enumerable).GetMethods().Where(m => m.Name == "Select") from p in m.GetParameters().Where(p => p.Name.Equals("selector")) where p.ParameterType.GetGenericArguments().Count() == 2 select p) { selectMethod = (MethodInfo)p.Member; } Expression selectExpression = Expression.Call( null, selectMethod.MakeGenericMethod(sourceGenericType, destGenericType), new[] { sourceExp, genericMemberQueryableExpression }); var destListAndCollTest = typeof(ICollection <>).MakeGenericType(destGenericType).IsAssignableFrom(destProp.PropertyType); if (destListAndCollTest) { var toArrayMethod = typeof(Enumerable).GetMethod("ToList"); selectExpression = Expression.Call(null, toArrayMethod.MakeGenericMethod(destGenericType), selectExpression); } _bindingExpressions.Add(destProp.Name, Expression.Bind(destProp, selectExpression)); } else { Expression expression; if (memberQueryableExpression != null) { var lambdaExpression = memberQueryableExpression as LambdaExpression; var projectionAccessMemberVisitor = new ProjectionAccessMemberVisitor(sourceExp.Type, sourceExp); var clearanceExp = projectionAccessMemberVisitor.Visit(lambdaExpression.Body); expression = Expression.Condition( Expression.Equal(sourceExp, Expression.Constant(null, sourceExp.Type)), Expression.Constant(null, destProp.PropertyType), clearanceExp); } else { expression = sourceExp; } _bindingExpressions.Add(destProp.Name, Expression.Bind(destProp, expression)); } }