IEnumerable <ExpandoObject> GetDataForSave(ExpandoObject data, String path, Int32?parentIndex = null) { if (String.IsNullOrEmpty(path)) { yield return(data); } var x = path.Split('.'); var currentData = data as IDictionary <String, Object>; var currentId = data.Get <Object>("Id"); for (int i = 0; i < x.Length; i++) { bool bLast = (i == (x.Length - 1)); String prop = x[i]; Object propValue; // RowNumber is 1-based! if (currentData.TryGetValue(prop, out propValue)) { if (propValue is IList <Object> ) { var list = propValue as IList <Object>; for (int j = 0; j < list.Count; j++) { var currVal = list[j] as ExpandoObject; currVal.Set("RowNumber", j + 1); currVal.Set("ParentId", currentId); if (parentIndex != null) { currVal.Set("ParentRowNumber", parentIndex.Value + 1); } if (bLast) { yield return(currVal); } else { String newPath = String.Empty; for (int k = i + 1; k < x.Length; k++) { newPath = newPath.AppendDot(x[k]); } foreach (var dx in GetDataForSave(currVal, newPath, j)) { yield return(dx); } } } } else if (propValue is ExpandoObject) { var currVal = propValue as ExpandoObject; if (bLast) { var propValEO = propValue as ExpandoObject; currVal.Set("ParentId", currentId); yield return(currVal); } else { String newPath = String.Empty; for (int k = i + 1; k < x.Length; k++) { newPath = newPath.AppendDot(x[k]); } foreach (var dx in GetDataForSave(currVal, newPath, 0)) { yield return(dx); } } } } } }
IEnumerable <ExpandoObject> GetDataForSave(ExpandoObject data, String path, Int32?parentIndex = null, Object parentKey = null, Guid?parentGuid = null) { if (String.IsNullOrEmpty(path)) { yield return(data); } var x = path.Split('.'); if (!(data is IDictionary <String, Object> currentData)) { throw new DataWriterException("There is no current data"); } var currentId = data.Get <Object>("Id"); Guid?currentGuid = null; for (Int32 i = 0; i < x.Length; i++) { Boolean bLast = (i == (x.Length - 1)); String prop = x[i]; // RowNumber is 1-based! Boolean isMap = false; if (prop.EndsWith("*")) { prop = prop.Substring(0, prop.Length - 1); isMap = true; } if (currentData.TryGetValue(prop, out Object propValue)) { if (propValue is IList <Object> ) { var list = propValue as IList <Object>; for (Int32 j = 0; j < list.Count; j++) { var currVal = list[j] as ExpandoObject; currVal.Set("RowNumber", j + 1); currVal.SetNotNull("ParentId", currentId); currVal.SetNotNull("ParentKey", parentKey); var rowGuid = currVal.GetOrCreate <Guid>("GUID", () => Guid.NewGuid()); if (parentIndex != null) { currVal.Set("ParentRowNumber", parentIndex.Value + 1); } currVal.SetNotNull("ParentGUID", parentGuid); if (bLast) { yield return(currVal); } else { String newPath = String.Empty; for (Int32 k = i + 1; k < x.Length; k++) { newPath = newPath.AppendDot(x[k]); } foreach (var dx in GetDataForSave(currVal, newPath, parentIndex:j, parentKey:null, parentGuid:rowGuid)) { yield return(dx); } } } } else if (propValue is ExpandoObject) { var currVal = propValue as ExpandoObject; if (bLast) { var propValEO = propValue as ExpandoObject; if (isMap) { var propValD = propValEO as IDictionary <String, Object>; foreach (var kv in propValD) { var mapItem = kv.Value as ExpandoObject; mapItem.Set("CurrentKey", kv.Key); if (parentIndex != null) { mapItem.Set("ParentRowNumber", parentIndex.Value + 1); } mapItem.SetNotNull("ParentGUID", parentGuid); yield return(mapItem); } } else { currVal.SetNotNull("ParentId", currentId); currVal.SetNotNull("ParentKey", parentKey); if (parentIndex != null) { currVal.Set("ParentRowNumber", parentIndex.Value + 1); } currentGuid = currVal.GetOrCreate <Guid>("GUID", () => Guid.NewGuid()); currVal.SetNotNull("ParentGUID", parentGuid); yield return(currVal); } } else { String newPath = String.Empty; for (Int32 k = i + 1; k < x.Length; k++) { newPath = newPath.AppendDot(x[k]); } if (isMap) { var currValD = currVal as IDictionary <String, Object>; foreach (var kv in currValD) { var mapItem = kv.Value as ExpandoObject; foreach (var dx in GetDataForSave(mapItem, newPath, parentIndex:parentIndex, parentKey:kv.Key, parentGuid:currentGuid)) { yield return(dx); } } } else { currentGuid = currVal.GetOrCreate <Guid>("GUID", () => Guid.NewGuid()); foreach (var dx in GetDataForSave(currVal, newPath, parentIndex:0, parentKey:null, parentGuid:currentGuid)) { yield return(dx); } } } } } } }