/// <summary> /// Converts the indicated value into a type that is compatible with fieldType. /// </summary> /// <param name="propertyValue">The value to be converted.</param> /// <param name="fieldType">The desired type.</param> /// <param name="mappedType"> /// GraphType for matching dictionary keys with <paramref name="type"/> property names. /// GraphType contains information about this matching in Metadata property. /// In case of configuring field as Field(x => x.FName).Name("FirstName") source dictionary /// will have 'FirstName' key but its value should be set to 'FName' property of created object. /// </param> /// <remarks>There is special handling for strings, IEnumerable<T>, Nullable<T>, and Enum.</remarks> public static object GetPropertyValue(this object propertyValue, Type fieldType, IGraphType mappedType = null) { // Short-circuit conversion if the property value already of the right type if (propertyValue == null || fieldType == typeof(object) || fieldType.IsInstanceOfType(propertyValue)) { return(propertyValue); } if (ValueConverter.TryConvertTo(propertyValue, fieldType, out object result)) { return(result); } var enumerableInterface = fieldType.Name == "IEnumerable`1" ? fieldType : fieldType.GetInterface("IEnumerable`1"); if (fieldType != typeof(string) && enumerableInterface != null) { IList newCollection; var elementType = enumerableInterface.GetGenericArguments()[0]; var underlyingType = Nullable.GetUnderlyingType(elementType) ?? elementType; var fieldTypeImplementsIList = fieldType.GetInterface("IList") != null; var propertyValueAsIList = propertyValue as IList; // Custom container if (fieldTypeImplementsIList && !fieldType.IsArray) { newCollection = (IList)Activator.CreateInstance(fieldType); } // Array of known size is created immediately else if (fieldType.IsArray && propertyValueAsIList != null) { newCollection = Array.CreateInstance(elementType, propertyValueAsIList.Count); } // List<T> else { var genericListType = typeof(List <>).MakeGenericType(elementType); newCollection = (IList)Activator.CreateInstance(genericListType); } if (!(propertyValue is IEnumerable valueList)) { return(newCollection); } // Array of known size is populated in-place if (fieldType.IsArray && propertyValueAsIList != null) { for (int i = 0; i < propertyValueAsIList.Count; ++i) { var listItem = propertyValueAsIList[i]; newCollection[i] = listItem == null ? null : GetPropertyValue(listItem, underlyingType, mappedType); } } // Array of unknown size is created only after populating list else { foreach (var listItem in valueList) { newCollection.Add(listItem == null ? null : GetPropertyValue(listItem, underlyingType, mappedType)); } if (fieldType.IsArray) { newCollection = ((dynamic)newCollection).ToArray(); } } return(newCollection); } var value = propertyValue; var nullableFieldType = Nullable.GetUnderlyingType(fieldType); // if this is a nullable type and the value is null, return null if (nullableFieldType != null && value == null) { return(null); } if (nullableFieldType != null) { fieldType = nullableFieldType; } if (propertyValue is IDictionary <string, object> objects) { return(ToObject(objects, fieldType, mappedType)); } if (fieldType.IsEnum) { if (value == null) { var enumNames = Enum.GetNames(fieldType); value = enumNames[0]; } if (!IsDefinedEnumValue(fieldType, value)) { throw new ExecutionError($"Unknown value '{value}' for enum '{fieldType.Name}'."); } string str = value.ToString(); value = Enum.Parse(fieldType, str, true); } return(ValueConverter.ConvertTo(value, fieldType)); }
private static object ConvertValue(object value, Type targetType) { return(ValueConverter.ConvertTo(value, targetType)); }