private static T ParseCollection <T>(this IRecord record, string identifier, IGraphClient graphClient) { var typeT = typeof(T).GetTypeInfo(); if (!typeT.IsGenericType && !typeT.IsArray) { throw new InvalidOperationException($"Don't know how to handle {typeof(T).FullName}"); } if (typeT.IsArray) { return(record.ParseArray <T>(identifier, graphClient)); } var genericArgs = typeT.GenericTypeArguments; if (genericArgs.Length > 1) { throw new InvalidOperationException($"Don't know how to handle {typeof(T).FullName}"); } var listType = typeof(List <>).MakeGenericType(genericArgs.Single()); var list = Activator.CreateInstance(listType); foreach (var item in (IEnumerable)record[identifier]) { var internalRecord = new Neo4jClientRecord(item, identifier); var method = GetParsed(genericArgs.Single()); var parsed = method.Invoke(null, internalRecord.AsParameters(graphClient)); listType.GetMethod("Add")?.Invoke(list, new[] { parsed }); } return((T)list); }
private static dynamic ParseElementInCollectionForAnonymous(IGraphClient graphClient, dynamic item, string identifier) { var newRecord = new Neo4jClientRecord(item, identifier); // item o gets parsed and returned always as a list when onlyReturnData = true var p2 = (List <dynamic>)ParseAnonymousAsDynamic(newRecord, graphClient, true); // but we only need the first item return(p2.First()); }
private static T Parse <T>(this IRecord record, string identifier, IGraphClient graphClient) { var typeT = typeof(T); if (typeT.IsPrimitive()) { return(record.ParsePrimitive <T>(identifier)); } if (typeT.GetTypeInfo().ImplementedInterfaces.Any(x => x.Name == nameof(IEnumerable)) && typeT.Name != nameof(ExpandoObject)) { return(record.ParseCollection <T>(identifier, graphClient)); } var converters = graphClient.JsonConverters; converters.Reverse(); var serializerSettings = new JsonSerializerSettings { Converters = converters, ContractResolver = graphClient.JsonContractResolver }; foreach (var jsonConverter in converters) { if (jsonConverter.CanConvert(typeof(T))) { return(JsonConvert.DeserializeObject <T>(record[identifier].As <INode>().ToJsonString(), serializerSettings)); } } var t = ConstructNew <T>(); var obj = record[identifier]; if (obj is INode node) { foreach (var property in t.GetType().GetProperties()) { if (node.Properties.ContainsKey(property.Name)) { if (property.PropertyType.IsPrimitive()) { property.SetValue(t, Convert.ChangeType(node.Properties[property.Name], property.PropertyType)); } else if (property.PropertyType.GetTypeInfo().ImplementedInterfaces.Any(i => i == typeof(IEnumerable))) { var parsed = GetParsed(property.PropertyType); var enumRecord = new Neo4jClientRecord(node.Properties[property.Name], "Enumerable"); var list = parsed.Invoke(null, enumRecord.AsParameters(graphClient)); property.SetValue(t, list); } else { var res = JsonConvert.DeserializeObject( $"\"{node.Properties[property.Name].As<string>()}\"", property.PropertyType, serializerSettings); property.SetValue(t, res); } } } } return(t); }
private static dynamic ParseAnonymousAsDynamic(this IRecord record, IGraphClient graphClient, bool onlyReturnData) { var data = new List <dynamic>(); var inner = new List <dynamic>(); foreach (var identifier in record.Keys) { dynamic expando = new ExpandoObject(); var t = (IDictionary <string, object>)expando; var obj = record[identifier]; if (obj == null) { inner.Add(null); } else if (obj is IPath path) { inner.Add(ParsePathResponse(path)); } else if (obj is INode node) { foreach (var property in node.Properties) { t[property.Key] = property.Value; } inner.Add(new Dictionary <string, dynamic> { { "data", expando } }); } else if (obj is IEnumerable && !(obj is string)) { var count = 0; var listObj = ((IEnumerable)obj).Cast <object>().ToList(); var first = listObj.FirstOrDefault(); if (first is KeyValuePair <string, object> ) { var newNode = new Neo4jClientNode(listObj.Cast <KeyValuePair <string, object> >()); dynamic expando2 = new ExpandoObject(); var t2 = (IDictionary <string, object>)expando2; foreach (var property in newNode.Properties) { t2[property.Key] = property.Value; } inner.Add(expando2); } else { foreach (var o in listObj) { var newRecord = new Neo4jClientRecord(o, identifier); var p2 = ParseAnonymousAsDynamic(newRecord, graphClient, true); inner.Add(p2); count++; } if (count == 0) { inner.Add(new object[0]); } } } else { var method = typeof(StatementResultHelper).GetMethod(nameof(Parse), BindingFlags.Static | BindingFlags.NonPublic); var generic = method?.MakeGenericMethod(obj.GetType()); var res = generic?.Invoke(null, new object[] { record, identifier, graphClient }); if (res == null) { throw new JsonSerializationException($"Unable to serialize {obj.GetType().FullName} correctly. This is likely an error and should be reported to Neo4jClient's github page."); } inner.Add(res); } } data.Add(inner); if (onlyReturnData) { return(inner); } //TODO: Ugh! this is about as hacky as it can get dynamic output = new { columns = new List <string>(record.Keys), data }; return(output); }