private static string GetIndexerInvocation(Expression expression, ParameterExpression[] parameters)
        {
            Expression          converted              = Expression.Convert(expression, typeof(object));
            ParameterExpression fakeParameter          = Expression.Parameter(typeof(object), null);
            Expression <Func <object, object> > lambda = Expression.Lambda <Func <object, object> >(converted, fakeParameter);
            Func <object, object> func;

            try
            {
                func = CachedExpressionCompiler.Process(lambda);
            }
            catch (InvalidOperationException ex)
            {
                throw new InvalidOperationException(
                          String.Format(
                              CultureInfo.CurrentCulture,
                              MvcResources.ExpressionHelper_InvalidIndexerExpression,
                              expression,
                              parameters[0].Name),
                          ex);
            }

            return("[" + Convert.ToString(func(null), CultureInfo.InvariantCulture) + "]");
        }
Exemple #2
0
        /// <summary>From lambda expression.</summary>
        ///
        /// <exception cref="ArgumentNullException">    Thrown when one or more required arguments are null.</exception>
        /// <exception cref="InvalidOperationException">Thrown when the requested operation is invalid.</exception>
        ///
        /// <typeparam name="TParameter">Type of the parameter.</typeparam>
        /// <typeparam name="TValue">    Type of the value.</typeparam>
        /// <param name="expression">The expression.</param>
        /// <param name="viewData">  Information describing the view.</param>
        ///
        /// <returns>A ModelMetadata.</returns>
        public static ModelMetadata FromLambdaExpression <TParameter, TValue>(
            Expression <Func <TParameter, TValue> > expression, ViewDataDictionary <TParameter> viewData)
        {
            if (expression == null)
            {
                throw new ArgumentNullException("expression");
            }
            if (viewData == null)
            {
                throw new ArgumentNullException("viewData");
            }

            string propertyName    = null;
            Type   containerType   = null;
            bool   legalExpression = false;

            // Need to verify the expression is valid; it needs to at least end in something
            // that we can convert to a meaningful string for model binding purposes

            switch (expression.Body.NodeType)
            {
            // ArrayIndex always means a single-dimensional indexer; multi-dimensional indexer is a method call to Get()
            case ExpressionType.ArrayIndex:
                legalExpression = true;
                break;

            // Only legal method call is a single argument indexer/DefaultMember call
            case ExpressionType.Call:
                legalExpression = ExpressionHelper.IsSingleArgumentIndexer(expression.Body);
                break;

            // Property/field access is always legal
            case ExpressionType.MemberAccess:
                var memberExpression = (MemberExpression)expression.Body;
                propertyName    = memberExpression.Member is PropertyInfo ? memberExpression.Member.Name : null;
                containerType   = memberExpression.Expression.Type;
                legalExpression = true;
                break;

            // Parameter expression means "model => model", so we delegate to FromModel
            case ExpressionType.Parameter:
                return(FromModel(viewData));
            }

            if (!legalExpression)
            {
                throw new InvalidOperationException(MvcResources.TemplateHelpers_TemplateLimitations);
            }

            TParameter    container     = viewData.Model;
            Func <object> modelAccessor = () => {
                try
                {
                    return(CachedExpressionCompiler.Process(expression)(container));
                }
                catch (NullReferenceException)
                {
                    return(null);
                }
            };

            return(GetMetadataFromProvider(modelAccessor, typeof(TValue), propertyName, containerType));
        }