Пример #1
0
        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));
            }
        }
Пример #2
0
        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));
            }
        }