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) + "]"); }
/// <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)); }