public ModelMetadata(ModelMetadataProvider provider, Type containerType, Func <object> modelAccessor, Type modelType, string propertyName) { if (provider == null) { throw new ArgumentNullException("provider"); } if (modelType == null) { throw new ArgumentNullException("modelType"); } Provider = provider; _containerType = containerType; _isRequired = !TypeHelpers.TypeAllowsNullValue(modelType); _modelAccessor = modelAccessor; _modelType = modelType; _propertyName = propertyName; }
private static ModelMetadata GetMetadataFromProvider(Func <object> modelAccessor, Type modelType, string propertyName, Type containerType, ModelMetadataProvider metadataProvider) { metadataProvider = metadataProvider ?? ModelMetadataProviders.Current; if (containerType != null && !String.IsNullOrEmpty(propertyName)) { return(metadataProvider.GetMetadataForProperty(modelAccessor, containerType, propertyName)); } return(metadataProvider.GetMetadataForType(modelAccessor, modelType)); }
internal static ModelMetadata FromStringExpression(string expression, ViewDataDictionary viewData, ModelMetadataProvider metadataProvider) { if (expression == null) { throw new ArgumentNullException("expression"); } if (viewData == null) { throw new ArgumentNullException("viewData"); } if (expression.Length == 0) // Empty string really means "model metadata for the current model" { return(FromModel(viewData, metadataProvider)); } ViewDataInfo vdi = viewData.GetViewDataInfo(expression); Type containerType = null; Type modelType = null; Func <object> modelAccessor = null; string propertyName = null; if (vdi != null) { if (vdi.Container != null) { containerType = vdi.Container.GetType(); } modelAccessor = () => vdi.Value; if (vdi.PropertyDescriptor != null) { propertyName = vdi.PropertyDescriptor.Name; modelType = vdi.PropertyDescriptor.PropertyType; } else if (vdi.Value != null) // We only need to delay accessing properties (for LINQ to SQL) { modelType = vdi.Value.GetType(); } } // Try getting a property from ModelMetadata if we couldn't find an answer in ViewData else if (viewData.ModelMetadata != null) { ModelMetadata propertyMetadata = viewData.ModelMetadata.Properties.Where(p => p.PropertyName == expression).FirstOrDefault(); if (propertyMetadata != null) { return(propertyMetadata); } } return(GetMetadataFromProvider(modelAccessor, modelType ?? typeof(string), propertyName, containerType, metadataProvider)); }
private static ModelMetadata FromModel(ViewDataDictionary viewData, ModelMetadataProvider metadataProvider) { return(viewData.ModelMetadata ?? GetMetadataFromProvider(null, typeof(string), null, null, metadataProvider)); }
internal static ModelMetadata FromLambdaExpression <TParameter, TValue>(Expression <Func <TParameter, TValue> > expression, ViewDataDictionary <TParameter> viewData, ModelMetadataProvider metadataProvider) { 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: MemberExpression 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, metadataProvider)); } if (!legalExpression) { throw new InvalidOperationException(SR.GetString(SR.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, metadataProvider)); }