/// <summary> /// Attempts to instatiate an object of type <paramref name="targetType"/> with data from <paramref name="resourceObject"/> using the <paramref name="apiResource"/>. /// </summary> /// <param name="resourceObject"></param> /// <param name="apiResource"></param> /// <param name="targetType"></param> /// <returns></returns> public static object ToObject(this JsonApiResourceObject resourceObject, JsonApiResource apiResource, Type targetType) { var result = Activator.CreateInstance(targetType); // extract id if (!string.IsNullOrWhiteSpace(resourceObject.Id)) { var idProp = targetType.GetProperty(apiResource.IdProperty); if (idProp != null) { var idObject = BtbrdCoreIdConverters.ConvertFromString(resourceObject.Id, idProp.PropertyType); idProp.SetValueFast(result, idObject); } } // TODO: better iterate over attributes and relations defined in the apiresource // extract attributes if (resourceObject.Attributes != null) { foreach (var attribute in resourceObject.Attributes) { var resourceAttribute = apiResource.Attributes.Where(a => a.Name == attribute.Key).FirstOrDefault(); if (resourceAttribute == null) { continue; } var targetProperty = targetType.GetProperty(resourceAttribute.PropertyName); if (targetProperty == null) { continue; } // Not handled: ienumerables of datetime,datetimeoffset and nullables var underlying = Nullable.GetUnderlyingType(targetProperty.PropertyType) ?? targetProperty.PropertyType; var value = attribute.Value; if (value != null) { if (underlying == typeof(DateTime)) { value = DateTime.Parse(value.ToString()); } else if (underlying == typeof(DateTimeOffset)) { value = DateTimeOffset.Parse(value.ToString()); } else if (underlying.IsEnum) { value = Enum.ToObject(underlying, Convert.ChangeType(value, Enum.GetUnderlyingType(underlying))); } else { value = Convert.ChangeType(value, underlying); } } targetProperty.SetValueFast(result, value); } } // extract relationships if (resourceObject.Relationships != null) { foreach (var relationship in resourceObject.Relationships) { var relationResource = apiResource.Relationships.Where(r => r.Name == relationship.Key).FirstOrDefault(); if (relationResource == null) { continue; } if (relationResource.Kind == RelationshipKind.BelongsTo) { var relationshipObject = relationship.Value as JsonApiToOneRelationshipObject; if (!string.IsNullOrWhiteSpace(relationshipObject.Data?.Id)) { var idProp = targetType.GetProperty(relationResource.IdPropertyName); if (idProp != null) { var idObject = BtbrdCoreIdConverters.ConvertFromString(relationshipObject.Data.Id, idProp.PropertyType); idProp.SetValueFast(result, idObject); } } } else { var idProp = targetType.GetProperty(relationResource.IdPropertyName) ?? throw new Exception($"{nameof(JsonApiResourceObjectExtensions)}: Could not find relation property {relationResource.IdPropertyName}"); // get type of the id (e.g. long, string, ..) Type innerType; if (idProp.PropertyType.IsArray) { innerType = idProp.PropertyType.GetElementType(); } else if (idProp.PropertyType.IsNonStringEnumerable()) #if (NET40) { innerType = idProp.PropertyType.GetGenericArguments()[0]; } #else { innerType = idProp.PropertyType.GenericTypeArguments[0]; } #endif else { throw new Exception($"{nameof(JsonApiResourceObjectExtensions)}: Trying to read the relation, could not find element-type of type {idProp.PropertyType.FullName}."); } if (!(relationship.Value is JsonApiToManyRelationshipObject relationshipObject)) { throw new Exception($"{nameof(JsonApiResourceObjectExtensions)}: Expected a {nameof(JsonApiToManyRelationshipObject)}, found {relationship.Value?.GetType().FullName ?? "null"}"); } // create List instance // get the below defined method GetIdCollection for T=innerType // and executes it. var instance = (typeof(JsonApiResourceObjectExtensions) .GetMethod(nameof(GetIdCollection)) ?.MakeGenericMethod(innerType) ?? throw new Exception($"{nameof(JsonApiResourceObjectExtensions)}: Method {nameof(GetIdCollection)} not found.")) .Invoke(null, new object[] { /* IEnumerable<JsonApiResourceIdentifierObject> ids : */ relationshipObject.Data, /* bool makeArray : */ idProp.PropertyType.IsArray }); idProp.SetValueFast(result, instance); }
public static JsonApiResourceObject GetResource(this JsonApiResourceObjectDictionary resourceDictionary, object id, Type type) { return(resourceDictionary.GetResource(BtbrdCoreIdConverters.ConvertToString(id), type.GetJsonApiClassName())); }
public static string GetIdAsString(this IJsonApiDataModel obj) { var info = obj.GetType().GetProperty("Id"); return(BtbrdCoreIdConverters.ConvertToString(info.GetValueFast(obj))); }
public static void SetIdFromString(this IJsonApiDataModel obj, string stringId) { var info = obj.GetType().GetProperty("Id"); info.SetValueFast(obj, BtbrdCoreIdConverters.ConvertFromString(stringId, info.PropertyType)); }
public static JsonApiResourceObject GetResource(this JsonApiResourceObjectDictionary resourceDictionary, object id, JsonApiResource apiResource) { return(resourceDictionary.GetResource(BtbrdCoreIdConverters.ConvertToString(id), apiResource.ResourceType)); }