private void TrySetSystemObjectValue(string key, PropertyInfo propertyInfo, string propertyName, Type containerType, ModelDictionaryResult result, object value) { var objModelMetadata = new ProxyModelMetadata(propertyInfo, ProxyModelMetadataIdentity.ForProperty(value.GetType(), propertyName, containerType)); if (objModelMetadata.IsSimpleType) { result.Dictionary.Add(key, Convert.ToString(value)); return; } if (objModelMetadata.IsEnumerableType) { if (objModelMetadata.ElementType.IsSimpleType) { SetSimpleEnumerable(key, result.Dictionary, value); } else { TrySetValueInner(key, objModelMetadata, result, value); } return; } // Anonymous object resolver for (int i = 0; i < objModelMetadata.Properties.Count; i++) { var modelMetadata = objModelMetadata.Properties[i]; var v = modelMetadata.PropertyInfo.GetValue(value); if (v != null) { ResolveInternal(modelMetadata, result, v, isTopLevelObject: false, prefix: key); } } }
private void InitializeTypeInformation() { var typeInfo = ModelType.GetTypeInfo(); IsComplexType = !TypeDescriptor.GetConverter(ModelType).CanConvertFrom(typeof(string)); IsNullableValueType = Nullable.GetUnderlyingType(ModelType) != null; IsReferenceType = !typeInfo.IsValueType; IsReferenceOrNullableType = !typeInfo.IsValueType || IsNullableValueType; UnderlyingOrModelType = Nullable.GetUnderlyingType(ModelType) ?? ModelType; IsFormFile = typeof(IFormFile).IsAssignableFrom(ModelType); IsSimpleType = IsSimple(ModelType); IsSystemObject = ModelType == typeof(object); var collectionType = ClosedGenericMatcher.ExtractGenericInterface(ModelType, typeof(ICollection <>)); IsCollectionType = collectionType != null; if (ModelType == typeof(string) || !typeof(IEnumerable).IsAssignableFrom(ModelType)) { // Do nothing, not Enumerable. } else if (ModelType.IsArray) { IsEnumerableType = true; var elementType = ModelType.GetElementType(); PropertyInfo propertyInfo = ContainerType?.GetProperty(PropertyName); if (propertyInfo != null) { ElementType = new ProxyModelMetadata(propertyInfo, ProxyModelMetadataIdentity.ForProperty(elementType, propertyInfo.Name, ModelType), reflectedType: _reflectedType); } IsFormFile = typeof(IFormFile).IsAssignableFrom(elementType); } else { IsEnumerableType = true; var enumerableType = ClosedGenericMatcher.ExtractGenericInterface(ModelType, typeof(IEnumerable <>)); var elementType = enumerableType?.GenericTypeArguments[0]; if (elementType != null) { IsFormFile = typeof(IFormFile).IsAssignableFrom(elementType); } if (elementType == null) { // ModelType implements IEnumerable but not IEnumerable<T>. elementType = typeof(object); } PropertyInfo propertyInfo = ContainerType?.GetProperty(PropertyName); if (propertyInfo != null) { ElementType = new ProxyModelMetadata(propertyInfo, ProxyModelMetadataIdentity.ForProperty(elementType, propertyInfo.Name, ModelType), reflectedType: _reflectedType); } } if (IsNullableValueType) { var elementType = Nullable.GetUnderlyingType(ModelType); PropertyInfo pInfo = ContainerType?.GetProperty(PropertyName); if (pInfo != null) { ElementType = new ProxyModelMetadata(pInfo, ProxyModelMetadataIdentity.ForProperty(elementType, pInfo.Name, ModelType), reflectedType: _reflectedType); } } if (IsComplexType && IsReferenceOrNullableType && (!IsEnumerableType && !IsCollectionType) && ModelType.Name != typeof(object).Name) { PropertyInfo[] properties = ModelType.GetProperties(); List <ProxyModelMetadata> metadataList = new List <ProxyModelMetadata>(); foreach (var prop in properties) { if (_reflectedType == null) { _reflectedType = prop.ReflectedType; } if (_reflectedType == prop.PropertyType) { // self reference loop continue; } if (ModelType == prop.PropertyType) { // Parent child ref - self reference loop continue; } metadataList.Add(new ProxyModelMetadata(prop, ProxyModelMetadataIdentity.ForProperty(prop.PropertyType, prop.Name, ModelType), reflectedType: _reflectedType)); } Properties = metadataList; } }