예제 #1
0
 /// <summary>
 /// 获取成员名称
 /// </summary>
 private static string GetMemberName(MemberExpression memberExpression)
 {
     if (memberExpression == null)
         return string.Empty;
     string result = memberExpression.ToString();
     return result.Substring(result.IndexOf(".") + 1);
 }
 protected override Expression VisitMemberAccess(MemberExpression m)
 {
     var result = m.ToString();
     return Expression.Constant(result.Substring(result.IndexOf('.') + 1));
 }
예제 #3
0
 internal override Expression VisitMemberAccess(MemberExpression m)
 {
     PropertyInfo info;
     Expression expression;
     Type type = m.Expression.Type;
     this.leafExpressionIsMemberAccess = true;
     if (PrimitiveType.IsKnownNullableType(type))
     {
         this.leafExpressionIsMemberAccess = false;
         return base.VisitMemberAccess(m);
     }
     if (ProjectionAnalyzer.IsCollectionProducingExpression(m.Expression))
     {
         throw new NotSupportedException(System.Data.Services.Client.Strings.ALinq_ExpressionNotSupportedInProjection(this.type, m.ToString()));
     }
     if (!ResourceBinder.PatternRules.MatchNonPrivateReadableProperty(m, out info, out expression))
     {
         throw new NotSupportedException(System.Data.Services.Client.Strings.ALinq_ExpressionNotSupportedInProjection(this.type, m.ToString()));
     }
     Expression expression2 = base.VisitMemberAccess(m);
     if (ClientTypeUtil.TypeOrElementTypeIsEntity(type))
     {
         Type type2;
         ResourceBinder.StripTo<Expression>(m.Expression, out type2);
         this.box.AppendPropertyToPath(info, type2, this.context);
         this.leafExpressionIsMemberAccess = false;
     }
     return expression2;
 }
예제 #4
0
        /// <summary>
        /// Visits member access.
        /// </summary>
        /// <param name="m">The expression.</param>
        /// <returns></returns>
        /// <exception cref="NotSupportedException">
        /// </exception>
        protected override Expression VisitMemberAccess(MemberExpression m)
        {
            //if(m.Expression.NodeType == ExpressionType.MemberAccess)
            //{
            //    VisitMemberAccess((MemberExpression)m.Expression);
            //}

            if (m.Expression != null && m.Expression.NodeType == ExpressionType.Parameter)
            {
                var alias = MongoConfiguration.GetPropertyAlias(m.Expression.Type, m.Member.Name);
                var id = TypeHelper.GetHelperForType(m.Expression.Type).FindIdProperty();
                if (id != null && id.Name == alias)
                {
                    alias = "_id";
                }
                if (UseScopedQualifier)
                {
                    _sb.Append("this.");
                }
                _sb.Append(alias);

                _lastFlyProperty = alias;
                return m;
            }

            if (m.Member.DeclaringType == typeof(string))
            {
                switch (m.Member.Name)
                {
                    case "Length":
                        _sb.Append("LEN(");
                        Visit(m.Expression);
                        _sb.Append(")");
                        return m;
                }
            }
            else if (m.Member.DeclaringType == typeof(DateTime) || m.Member.DeclaringType == typeof(DateTimeOffset))
            {
                #region DateTime Magic
                var fullName = m.ToString().Split(new[] { '.' }, StringSplitOptions.RemoveEmptyEntries);

                // this is complex
                IsComplex = true;

                // this is a DateProperty hanging off the property - clip the last 2 elements
                var fixedName = fullName.Skip(1).Take(fullName.Length - 2).ToArray();
                var propName = string.Join(".", fixedName);

                // now we get to do some tricky fun with javascript
                switch (m.Member.Name)
                {
                    case "Day":
                        Visit(m.Expression);
                        _sb.Append(".getDate()");
                        return m;
                    case "Month":
                        Visit(m.Expression);
                        _sb.Append(".getMonth()");
                        return m;
                    case "Year":
                        Visit(m.Expression);
                        _sb.Append(".getFullYear()");
                        return m;
                    case "Hour":
                        Visit(m.Expression);
                        _sb.Append(".getHours()");
                        return m;
                    case "Minute":
                        Visit(m.Expression);
                        _sb.Append(".getMinutes()");
                        return m;
                    case "Second":
                        Visit(m.Expression);
                        _sb.Append(".getSeconds()");
                        return m;
                    case "DayOfWeek":
                        Visit(m.Expression);
                        _sb.Append(".getDay()");
                        return m;
                }
                #endregion
            }
            else
            {
                var fullName = m.ToString().Split(new[] { '.' }, StringSplitOptions.RemoveEmptyEntries);

                // this supports the "deep graph" name - "Product.Address.City"
                var fixedName = fullName.Skip(1).Take(fullName.Length - 1).ToArray();

                String result = "";

                if (m.Expression.NodeType == ExpressionType.Constant)
                {
                    var constant = m.Expression as ConstantExpression;
                    var fi = (FieldInfo)m.Member;
                    var val = fi.GetValue(constant.Value);
                    if (val is String)
                    {
                        result = String.Format("\"{0}\"", val);
                    }
                    else
                    {
                        result = val.ToString();
                    }
                    SetFlyValue(val);
                }
                else
                {
                    var expressionRootType = GetParameterExpression((MemberExpression)m.Expression);

                    if (expressionRootType != null)
                    {
                        fixedName = GetDeepAlias(expressionRootType.Type, fixedName);
                    }

                    result = string.Join(".", fixedName);
                    //sb.Append("this." + result);
                    if (UseScopedQualifier)
                    {
                        _sb.Append("this.");
                    }
                }
                _sb.Append(result);

                _lastFlyProperty = result;
                return m;
            }

            // if this is a property NOT on the object...
            throw new NotSupportedException(string.Format("The member '{0}' is not supported", m.Member.Name));
        }
예제 #5
0
        private string TranslateOneToMany(string functionName, MemberExpression memberExpression, LambdaExpression fieldExpression, LambdaExpression filterExpression)
        {
            if (!string.IsNullOrEmpty(TranslateMember(memberExpression))) // this shouldn't return any SQL
                throw new SqlExpressionTranslatorException(memberExpression.ToString());

            var relation = GetRelation(memberExpression.Expression, memberExpression.Member.Name);

            if (relation == null)
                throw new SqlExpressionTranslatorException(memberExpression.ToString());

            if (fieldExpression != null && filterExpression != null && fieldExpression.Parameters[0] != filterExpression.Parameters[0])
                throw new SqlExpressionTranslatorException(null);

            var iterator = fieldExpression != null ? fieldExpression.Parameters[0] : filterExpression != null ? filterExpression.Parameters[0] : Expression.Parameter(relation.ElementType);

            LambdaExpression relationExpression = CreateToManyFilterExpression(relation, memberExpression.Expression, filterExpression, iterator);

            var template = _toManyTemplates[functionName];

            if (template == null)
                throw new NotSupportedException(functionName);

            var alias = SqlNameGenerator.NextTableAlias();

            _metaData[iterator] = new ExpressionMetaData { Iterator = iterator, Relation = relation, Schema = relation.ForeignSchema };

            _relationAliases[iterator] = new Dictionary<object, string> { { relation, alias } };

            _subQueries.Push(new SubQuery());

            string sqlFields = Translate(fieldExpression);
            string sqlWhere = Translate(relationExpression);
            string sqlJoins = (Joins.Count > 0) ? string.Join(" ", Joins.Select(join => join.ToSql(_sqlDialect))) : null;

            _subQueries.Pop();

            return string.Format(template,
                                    sqlFields,
                                    _sqlDialect.QuoteTable(relation.ForeignSchema.MappedName) + " " + alias, sqlJoins ?? "",
                                    sqlWhere
                                );
        }
예제 #6
0
        private static bool MemberExpressionsEqual(MemberExpression x, MemberExpression y, LambdaExpression rootX, LambdaExpression rootY)
        {
            // Special case for static field and static property
            if (x.Expression == null)
            {
                return Equals(x.Member, y.Member);
            }

            if (x.Expression.NodeType != y.Expression.NodeType)
                return false;
            switch (x.Expression.NodeType)
            {
                case ExpressionType.Constant:
                    var constx = GetValueOfConstantExpression(x);
                    var consty = GetValueOfConstantExpression(y);
                    return Equals(constx, consty);
                case ExpressionType.Parameter:
                case ExpressionType.MemberAccess:
                    return Equals(x.Member, y.Member) && ExpressionEqual(x.Expression, y.Expression, rootX, rootY);
                case ExpressionType.New:
                case ExpressionType.Call:
                    return ExpressionEqual(x.Expression, y.Expression, rootX, rootY);
                default:
                    throw new NotImplementedException(x.ToString());
            }
        }
예제 #7
0
            /// <summary>
            /// Visits a member access expression in non-entity projections, validating that
            /// it's correct and recording the path visit to include in a projection if necessary.
            /// </summary>
            /// <param name="m">Expression to visit.</param>
            /// <returns>The same expression.</returns>
            /// <remarks>
            /// The projection analyzer runs after funcletization, so a member expression
            /// rather than a constant expression implies that this is correlated to
            /// a parameter, by dotting through the argument in valid cases, and possibly
            /// more complex cases in others like new DSC(p.Orders)*.Foo* &lt;- .Foo is invalid.
            /// </remarks>
            internal override Expression VisitMemberAccess(MemberExpression m)
            {
                Debug.Assert(m != null, "m != null");

                // if primitive or nullable primitive, allow member access... i.e. calling Value on nullable<int>
                if (ClientConvert.IsKnownNullableType(m.Expression.Type))
                {
                    return base.VisitMemberAccess(m);
                }

                // Only allowed to project entities
                if (!ClientType.CheckElementTypeIsEntity(m.Expression.Type) || IsCollectionProducingExpression(m.Expression))
                {
                    throw new NotSupportedException(Strings.ALinq_ExpressionNotSupportedInProjection(this.type, m.ToString()));
                }

                PropertyInfo pi = null;
                if (ResourceBinder.PatternRules.MatchNonPrivateReadableProperty(m, out pi))
                {
                    Expression e = base.VisitMemberAccess(m);
                    box.AppendToPath(pi);
                    return e;
                }

                throw new NotSupportedException(Strings.ALinq_ExpressionNotSupportedInProjection(this.type, m.ToString()));
            }
        private BsonValue TranslateMemberAccess(MemberExpression node)
        {
            BsonValue result;
            if (node.Expression.Type == typeof(DateTime)
                && TryTranslateDateTimeMemberAccess(node, out result))
            {
                return result;
            }

            if (node.Expression != null
                && (node.Expression.Type.ImplementsInterface(typeof(ICollection<>))
                    || node.Expression.Type.ImplementsInterface(typeof(ICollection)))
                && node.Member.Name == "Count")
            {
                return new BsonDocument("$size", TranslateValue(node.Expression));
            }

            var message = string.Format("Member {0} of type {1} in the expression tree {2} cannot be translated.",
                node.Member.Name,
                node.Member.DeclaringType,
                node.ToString());
            throw new NotSupportedException(message);
        }
        // 
        // Listing 12-38 (continue)
        // 
        /// <summary>
        /// We support only TotalMinutes and TotalHours comparison
        /// </summary>
        private void TranslateTimeSpanComparison(
            ExpressionType nodeType,
            ConstantExpression constant,
            MemberExpression memberAccess)
        {

            MemberExpression parent = memberAccess.Expression as MemberExpression;
            if (parent.Member.ReflectedType != typeof(ImageInformation))
            {
                throw new NotSupportedException(
                    string.Format(
                        "Member {0} is not of type Images",
                        memberAccess.ToString()));
            }

            // We support only TotalMinutes for this simple provider
            if ((memberAccess.Member.Name == "TotalMinutes")
                && (parent.Member.Name == "TimeToArrival"))
            {
                SetIntParameter(
                    (int)GetDoubleConstant(constant),
                    ref queryParameters.Filter.MaxDaysTaken,
                    ref queryParameters.Filter.MaxDaysTaken,
                    nodeType);
            }
            else 
            {
                throw new NotSupportedException(
                    string.Format(
                        "Query on {0} expression is not supported",
                        memberAccess.ToString()));
            }
        }
        /// <summary>
        /// The standard case supports an equal condition for strings
        /// and other comparisons for GroundSpeed and Altitude integers
        /// </summary>
        private void TranslateStandardComparisons(
            ExpressionType nodeType,
            ConstantExpression constant,
            MemberExpression memberAccess)
        {

            string stringFieldName =
                (from field in typeof(ImageInformation).GetProperties()
                 where Type.GetTypeCode(field.PropertyType) == TypeCode.String
                       && field.Name == memberAccess.Member.Name
                 select field.Name).FirstOrDefault();

            // Loop for all strings 
            if (stringFieldName != null)
            {
                if (nodeType != ExpressionType.Equal)
                {
                    throw new NotSupportedException(
                        string.Format(
                            "The binary operator '{0}' is not supported on {1} member",
                            nodeType,
                            memberAccess.Member.Name));
                }
                queryParameters.Filter.GetType()
                    .GetField(stringFieldName)
                    .SetValue(queryParameters.Filter, constant.Value);
            }
            else
            {
                // String not found
                switch (memberAccess.Member.Name)
                {
                    case "DateTaken":
                        //SetDateTimeParameter(
                        //    constant.Value.ToString(),
                        //    ref queryParameters.Filter.MinDateTaken,
                        //    ref queryParameters.Filter.MaxDateTaken,
                        //    nodeType);
                        //break;
                    default:
                        throw new NotSupportedException(
                            string.Format("Condition on member {0} is not supported",
                            memberAccess.ToString()));
                }
            }
        }
        /// <summary>
        /// Process member references.
        /// </summary>
        /// <param name="expression">
        /// The expression to visit.
        /// </param>
        /// <returns>
        /// The visited expression.
        /// </returns>
        private Expression VisitMemberAccess(MemberExpression expression)
        {
            // Lookup the Mobile Services name of the member and use that
            string memberName = GetTableMemberName(expression, this.contractResolver);
            if (memberName != null)
            {
                this.filterExpression.Push(new MemberAccessNode(null, memberName));
                return expression;
            }
            
            // Check if this member is actually a function that looks like a
            // property (like string.Length, etc.)
            string methodName = null;
            MemberInfoKey memberInfoKey = new MemberInfoKey(expression.Member);
            if (InstanceProperties.TryGetValue(memberInfoKey, out methodName))
            {
                var fnCallNode = new FunctionCallNode(methodName, null);
                this.filterExpression.Push(fnCallNode);

                this.Visit(expression.Expression);

                this.SetChildren(fnCallNode);

                return expression;
            }

            // Otherwise we can't process the member.
            throw new NotSupportedException(
                string.Format(
                    CultureInfo.InvariantCulture,
                    "The member '{0}' is not supported in the 'Where' Mobile Services query expression '{1}'.",
                    expression != null && expression.Member != null ? expression.Member.Name : null,
                    expression != null ? expression.ToString() : null));
        }
예제 #12
0
        private string TranslateMember(MemberExpression node)
        {
            if (node.Expression.Type == typeof(string) && node.Member.Name == "Length")
            {
                string fnName = _sqlDialect.SqlFunction(SqlDialect.Function.StringLength, Translate(node.Expression));

                if (fnName != null)
                    return fnName;
            }

            if (Translate(node.Expression) != null)
                throw new SqlExpressionTranslatorException(node.ToString());

            string sql = ProcessRelation(node, node.Expression, node.Member.Name);

            if (sql != null)
            {
                if (node.Type == typeof (bool))
                {
                    return TranslateTrue(_sqlDialect.QuoteField(sql));
                }
                else
                    return _sqlDialect.QuoteField(sql);
            }

            return null;
        }
예제 #13
0
        /// <summary>
        /// Visits member access.
        /// </summary>
        /// <param name="m">The expression.</param>
        /// <returns></returns>
        /// <exception cref="NotSupportedException">
        /// </exception>
        protected override Expression VisitMemberAccess(MemberExpression m)
        {
            if (m.Expression != null && m.Expression.NodeType == ExpressionType.Parameter)
            {
                var alias = MongoConfiguration.GetPropertyAlias(m.Expression.Type, m.Member.Name);
                var id = TypeHelper.GetHelperForType(m.Expression.Type).FindIdProperty();
                if (id != null && id.Name == alias)
                {
                    alias = "_id";
                }

                if (UseScopedQualifier)
                {
                    _sbWhere.Append("this.");
                }

                _sbWhere.Append(alias);
                _lastFlyProperty = alias;
                return m;
            }

            if (m.Member.DeclaringType == typeof(string))
            {
                switch (m.Member.Name)
                {
                    case "Length":
                        IsComplex = true;
                        Visit(m.Expression);
                        _sbWhere.Append(".length");
                        return m;
                }
            }
            else if (m.Member.DeclaringType == typeof(DateTime) || m.Member.DeclaringType == typeof(DateTimeOffset))
            {
                #region DateTime Magic
                // this is complex
                IsComplex = true;

                // now we get to do some tricky fun with javascript
                switch (m.Member.Name)
                {
                    case "Day":
                        Visit(m.Expression);
                        _sbWhere.Append(".getDate()");
                        return m;
                    case "Month":
                        Visit(m.Expression);
                        _sbWhere.Append(".getMonth()");
                        return m;
                    case "Year":
                        Visit(m.Expression);
                        _sbWhere.Append(".getFullYear()");
                        return m;
                    case "Hour":
                        Visit(m.Expression);
                        _sbWhere.Append(".getHours()");
                        return m;
                    case "Minute":
                        Visit(m.Expression);
                        _sbWhere.Append(".getMinutes()");
                        return m;
                    case "Second":
                        Visit(m.Expression);
                        _sbWhere.Append(".getSeconds()");
                        return m;
                    case "DayOfWeek":
                        Visit(m.Expression);
                        _sbWhere.Append(".getDay()");
                        return m;
                }
                #endregion
            }
            else
            {
                // this supports the "deep graph" name - "Product.Address.City"
                var fullName = m.ToString().Split(new[] { '.' }, StringSplitOptions.RemoveEmptyEntries);

                var fixedName = fullName
                    .Skip(1)
                    .Where(x => x != "First()")
                    .Select(x => Regex.Replace(x, @"\[[0-9]+\]$", ""))
                    .ToArray();

                var expressionRootType = GetParameterExpression(m.Expression);
                if (expressionRootType != null)
                {
                    fixedName = GetDeepAlias(expressionRootType.Type, fixedName);
                }

                if (UseScopedQualifier)
                {
                    _sbWhere.Append("this.");
                }

                string result = string.Join(".", fixedName);

                _sbWhere.Append(result);
                _lastFlyProperty = result;

                return m;
            }

            // if this is a property NOT on the object...
            throw new NotSupportedException(string.Format("The member '{0}' is not supported", m.Member.Name));
        }
예제 #14
0
        private string VisitDeepAlias(MemberExpression m)
        {
            var fullName = m.ToString().Split(new[] { '.' }, StringSplitOptions.RemoveEmptyEntries);

            var fixedName = fullName
                .Skip(1)
                .Select(x => Regex.Replace(x, @"^get_Item\(([0-9]+)\)$", "$1|Ind"))
                .Select(x => Regex.Replace(x, @"\[([0-9]+)\]$", "$1|Ind"))
                .Select(x => x.Replace("First()", "0|Ind"))
                .ToArray();

            if (!_isDeepGraphWithArrays)
                _isDeepGraphWithArrays = fullName.Length - fixedName.Length != 1;

            var expressionRootType = GetParameterExpression(m.Expression);
            if (expressionRootType != null)
            {
                fixedName = GetDeepAlias(expressionRootType.Type, fixedName);
            }

            string result = string.Join(".", fixedName.Select(x => x.Replace("|Ind", "")).ToArray());

            return result;
        }
예제 #15
0
            internal override Expression VisitMemberAccess(MemberExpression m)
            {
                Debug.Assert(m != null, "m != null");

                if (!ClientType.CheckElementTypeIsEntity(m.Expression.Type) || IsCollectionProducingExpression(m.Expression))
                {
                    throw new NotSupportedException(Strings.ALinq_ExpressionNotSupportedInProjectionToEntity(this.type, m.ToString()));
                }

                PropertyInfo pi = null;
                if (ResourceBinder.PatternRules.MatchNonPrivateReadableProperty(m, out pi))
                {
                    Expression e = base.VisitMemberAccess(m);
                    box.AppendToPath(pi);
                    return e;
                }

                throw new NotSupportedException(Strings.ALinq_ExpressionNotSupportedInProjectionToEntity(this.type, m.ToString()));
            }
            internal override Expression VisitMemberAccess(MemberExpression m)
            {
                Debug.Assert(m != null, "m != null");

                if (ClientConvert.IsKnownNullableType(m.Expression.Type))
                {
                    return base.VisitMemberAccess(m);
                }

                if (!CommonUtil.IsClientType(m.Expression.Type))
                {
                    throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, SR.ALinqExpressionNotSupportedInProjection, this.type, m.ToString()));
                }

                PropertyInfo pi = null;
                if (ResourceBinder.PatternRules.MatchNonPrivateReadableProperty(m, out pi))
                {
                    Expression e = base.VisitMemberAccess(m);
                    this.box.AppendToPath(pi);
                    return e;
                }

                throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, SR.ALinqExpressionNotSupportedInProjection, this.type, m.ToString()));
            }
예제 #17
0
 private string MemberExprToSql(MemberExpression memberExpr, bool isCondition)
 {
     if (groupKeySql != null &&
         memberExpr.Member.DeclaringType.IsGenericType &&
         memberExpr.Member.Name == "Key" &&
         memberExpr.Member.DeclaringType.GetGenericTypeDefinition() == typeof(IGroup<,>))
         return groupKeySql;
     if (memberExpr.Member.DeclaringType == typeof(TimeSpan))
         return TimeStampPropToSql(memberExpr);
     var constExpr = memberExpr.Expression as ConstantExpression;
     if (constExpr != null)
         return ClosureMemberToSql(constExpr.Value, memberExpr.Member);
     var target = memberExpr.Expression != null ? ExpressionToSql(memberExpr.Expression, false) : null;
     var standard = MemberAccessToSql(memberExpr.Member, target);
     if (standard != null)
         return standard;
     var paramExpr = memberExpr.Expression as ParameterExpression;
     if (paramExpr != null)
     {
         var suffix = isCondition && memberExpr.Type == typeof(bool) ? " = 1" : "";
         return string.Format("{0}.[{1}]{2}", 
             ParamExprToSql(paramExpr), 
             nameResolver.ResolveColumnName(memberExpr.Member),
             suffix);
     }
     var innerMemberExpr = memberExpr.Expression as MemberExpression;
     if (innerMemberExpr != null)
         return InnerMemberExprToSql(innerMemberExpr, memberExpr.Member);
     throw new NotSupportedException(string.Format("Can not translate expression: {0}.", memberExpr.ToString()));
 }
        /// <summary>
        /// Process member references.
        /// </summary>
        /// <param name="expression">
        /// The expression to visit.
        /// </param>
        /// <returns>
        /// The visited expression.
        /// </returns>
        private Expression VisitMemberAccess(MemberExpression expression)
        {
            // Lookup the Mobile Services name of the member and use that
            string memberName = GetTableMemberName(expression, this.contractResolver);
            if (memberName != null)
            {
                this.filter.Append(memberName);
                return expression;
            }
            
            // Check if this member is actually a function that looks like a
            // property (like string.Length, etc.)
            string methodName = null;
            MemberInfoKey memberInfoKey = new MemberInfoKey(expression.Member);
            if (InstanceProperties.TryGetValue(memberInfoKey, out methodName))
            {
                this.filter.Append(methodName);
                this.filter.Append("(");
                this.Visit(expression.Expression);
                this.filter.Append(")");
                return expression;
            }

            // Otherwise we can't process the member.
            throw new NotSupportedException(
                string.Format(
                    CultureInfo.InvariantCulture,
                    Resources.FilterBuildingExpressionVisitor_MemberUnsupported,
                    expression != null && expression.Member != null ? expression.Member.Name : null,
                    expression != null ? expression.ToString() : null));
        }
예제 #19
0
 private string GetCode(MemberExpression memberExpression)
 {
     return memberExpression.ToString();
 }
예제 #20
0
        /// <summary>
        /// Visits member access.
        /// </summary>
        /// <param name="m">The expression.</param>
        /// <returns></returns>
        /// <exception cref="NotSupportedException">
        /// </exception>
        protected override Expression VisitMemberAccess(MemberExpression m)
        {
            var fullName = m.ToString().Split(new[] { '.' }, StringSplitOptions.RemoveEmptyEntries);

            if (m.Expression != null && m.Expression.NodeType == ExpressionType.Parameter)
            {
                var alias = MongoConfiguration.GetPropertyAlias(m.Expression.Type, m.Member.Name);
                sb.Append("this." + alias); // m.Member.Name);
                lastFlyProperty = alias; // m.Member.Name;
                return m;
            }
            if (m.Member.DeclaringType == typeof(string))
            {
                switch (m.Member.Name)
                {
                    case "Length":
                        sb.Append("LEN(");
                        Visit(m.Expression);
                        sb.Append(")");
                        return m;
                }
            }
            else if (m.Member.DeclaringType == typeof(DateTime) || m.Member.DeclaringType == typeof(DateTimeOffset))
            {
                // this is complex
                IsComplex = true;

                // this is a DateProperty hanging off the property - clip the last 2 elements
                var fixedName = fullName.Skip(1).Take(fullName.Length - 2).ToArray();
                var propName = string.Join(".", fixedName);

                // now we get to do some tricky fun with javascript
                switch (m.Member.Name)
                {
                    case "Day":
                        Visit(m.Expression);
                        sb.Append(".getDate()");
                        return m;
                    case "Month":
                        Visit(m.Expression);
                        sb.Append(".getMonth()");
                        return m;
                    case "Year":
                        Visit(m.Expression);
                        sb.Append(".getFullYear()");
                        return m;
                    case "Hour":
                        Visit(m.Expression);
                        sb.Append(".getHours()");
                        return m;
                    case "Minute":
                        Visit(m.Expression);
                        sb.Append(".getMinutes()");
                        return m;
                    case "Second":
                        Visit(m.Expression);
                        sb.Append(".getSeconds()");
                        return m;
                    case "DayOfWeek":
                        Visit(m.Expression);
                        sb.Append(".getDay()");
                        return m;
                }
            }
            else
            {
                // this supports the "deep graph" name - "Product.Address.City"
                var fixedName = fullName.Skip(1).Take(fullName.Length - 1).ToArray();

                var expressionRootType = GetParameterExpression((MemberExpression)m.Expression);

                if (expressionRootType != null)
                {
                    fixedName = GetDeepAlias(expressionRootType.Type, fixedName);
                }

                var result = string.Join(".", fixedName);
                sb.Append("this." + result);
                lastFlyProperty = result;
                return m;
            }

            // if this is a property NOT on the object...
            throw new NotSupportedException(string.Format("The member '{0}' is not supported", m.Member.Name));
        }
예제 #21
0
            internal override Expression VisitMemberAccess(MemberExpression m)
            {
                Debug.Assert(m != null, "m != null");

                this.leafExpressionIsMemberAccess = true;

                // Only allowed to project entities
                if (!ClientTypeUtil.TypeOrElementTypeIsEntity(m.Expression.Type) ||
                    IsCollectionProducingExpression(m.Expression))
                {
                    throw new NotSupportedException(Strings.ALinq_ExpressionNotSupportedInProjectionToEntity(this.type, m.ToString()));
                }

                PropertyInfo pi;
                Expression boundTarget;
                if (ResourceBinder.PatternRules.MatchNonPrivateReadableProperty(m, out pi, out boundTarget))
                {
                    Expression e = base.VisitMemberAccess(m);
                    Type convertedType;
                    ResourceBinder.StripTo<Expression>(m.Expression, out convertedType);
                    this.builder.AppendPropertyToPath(pi, convertedType, this.context);

                    this.leafExpressionIsMemberAccess = false;
                    return e;
                }

                throw new NotSupportedException(Strings.ALinq_ExpressionNotSupportedInProjectionToEntity(this.type, m.ToString()));
            }
예제 #22
0
        private string TranslateMember(MemberExpression node)
        {
            if (node.Expression.Type == typeof(string) && node.Member.Name == "Length")
            {
                string fnName = _sqlDialect.SqlFunction(SqlDialect.Function.StringLength, Translate(node.Expression));

                if (fnName != null)
                    return fnName;
            }

            if (Translate(node.Expression) != null)
                throw new SqlExpressionTranslatorException(node.ToString());

            var memberName = node.Member.Name;
            var field      = _schema.FieldsByFieldName[memberName];

            if (field != null && !String.IsNullOrEmpty(field.MappedName))
            {
                memberName = field.MappedName;
            }

            string sql = ProcessRelation(node, node.Expression, memberName);

            if (sql != null)
            {
                if (node.Type == typeof (bool))
                {
                    return TranslateTrue(_sqlDialect.QuoteField(sql));
                }
                else
                    return _sqlDialect.QuoteField(sql);
            }

            return null;
        }
예제 #23
0
            /// <summary>
            /// Visits a member access expression in non-entity projections, validating that
            /// it's correct and recording the path visit to include in a projection if necessary.
            /// </summary>
            /// <param name="m">Expression to visit.</param>
            /// <returns>The same expression.</returns>
            /// <remarks>
            /// The projection analyzer runs after funcletization, so a member expression
            /// rather than a constant expression implies that this is correlated to
            /// a parameter, by dotting through the argument in valid cases, and possibly
            /// more complex cases in others like new DSC(p.Orders)*.Var1* &lt;- .Var1 is invalid.
            /// </remarks>
            internal override Expression VisitMemberAccess(MemberExpression m)
            {
                Debug.Assert(m != null, "m != null");
                Type expressionType = m.Expression.Type;

                this.leafExpressionIsMemberAccess = true;

                // if primitive or nullable primitive, allow member access... i.e. calling Value on nullable<int>
                if (PrimitiveType.IsKnownNullableType(expressionType))
                {
                    this.leafExpressionIsMemberAccess = false;
                    return base.VisitMemberAccess(m);
                }

                // Only allowed to project entities, also it is ok to do client side projections on complex types.
                // Details on the fix for "Inconsistency between Count() method call and Count property projection on clr type collections":
                //     Relax check to only throw if IsCollectionProducingExpression returns true. 
                //     This enables client side projections (for example "Count") on Clr type collections, like ReadOnlyCollection (which is used in spatial types), ICollection, IList, etc.
                //     We already allow client side method calls (like Linq extension method "Count()") on clr type collections, so it makes client side projections consistent.
                //     Note: it will still throw for List<T> (because IsCollectionProducingExpression returns true for List<T>),
                //           however this is consistent with how we handle MethodCallExpression on clr type collections 
                //           and changing IsCollectionProducingExpression seems risky at this point as it's used in a lot of places.
                if (IsCollectionProducingExpression(m.Expression))
                {
                    throw new NotSupportedException(Strings.ALinq_ExpressionNotSupportedInProjection(this.type, m.ToString()));
                }
                
                PropertyInfo pi;
                Expression boundTarget;
                if (ResourceBinder.PatternRules.MatchNonPrivateReadableProperty(m, out pi, out boundTarget))
                {
                    Expression e = base.VisitMemberAccess(m);
                    if (ClientTypeUtil.TypeOrElementTypeIsEntity(expressionType))
                    {
                        Type convertedType;
                        ResourceBinder.StripTo<Expression>(m.Expression, out convertedType);
                        this.builder.AppendPropertyToPath(pi, convertedType, this.context);
                        this.leafExpressionIsMemberAccess = false;
                    }

                    return e;
                }

                throw new NotSupportedException(Strings.ALinq_ExpressionNotSupportedInProjection(this.type, m.ToString()));
            }
        /// <summary>
        /// Process member references.
        /// </summary>
        /// <param name="expression">The expression to visit.</param>
        /// <returns>The visited expression.</returns>
        protected override Expression VisitMember(MemberExpression expression)
        {
            // Lookup the Mobile Services name of the member and use that
            SerializableMember member = GetTableMember(expression);
            if (member != null)
            {
                this.filter.Append(member.Name);

                this.MarkVisited();
                return expression;
            }
            
            // Check if this member is actually a function that looks like a
            // property (like string.Length, etc.)
            string methodName = null;
            if (instanceProperties.TryGetValue(expression.Member, out methodName))
            {
                this.filter.Append(methodName);
                this.filter.Append("(");
                this.Visit(expression.Expression);
                this.filter.Append(")");

                this.MarkVisited();
                return expression;
            }

            // Otherwise we can't process the member.
            throw new NotSupportedException(
                string.Format(
                    CultureInfo.InvariantCulture,
                    Resources.FilterBuildingExpressionVisitor_VisitMember_Unsupported,
                    expression != null && expression.Member != null ? expression.Member.Name : null,
                    expression != null ? expression.ToString() : null));
        }
        private string GetMemberNameFromMemberAccess(MemberExpression memberExpression, ParameterExpression[] parameters)
        {
            if (memberExpression == null)
            {
                throw new NotSupportedException();
            }
            var expressionName = memberExpression.ToString();
            var subStrings = expressionName.Split('.');
            var isDeepParameter = false;
            if (subStrings.Length > 0 && parameters != null && parameters.Length > 0)
            {
                isDeepParameter = parameters[0].ToString() == subStrings[0];
            }
            if (memberExpression.NodeType == ExpressionType.MemberAccess && isDeepParameter)
            {
                var name = FindDeepParameter(memberExpression);

                if (name.ToLower() == "id")
                {
                    name = "_id";
                }
                return name;
            }
            throw new NotSupportedException(string.Format("Cannot OrderBy {0}", memberExpression.NodeType));
        }