private static List <Expression> BuildExtractionOfChildModelSetter([NotNull] Type currNodeType, [NotNull] Expression currNodeExpression, [NotNull] Expression valueToSetExpression, [NotNull, ItemNotNull] string[] pathParts) { var statements = new List <Expression>(); for (var partIndex = 0; partIndex < pathParts.Length; ++partIndex) { var name = TemplateDescriptionHelper.GetPathPartName(pathParts[partIndex]); var newNodeType = currNodeType.GetProperty(name)?.PropertyType; currNodeType = newNodeType ?? throw new ObjectPropertyExtractionException($"Type '{currNodeType}' has no property '{name}'"); currNodeExpression = Expression.Property(currNodeExpression, name); if (TemplateDescriptionHelper.IsCollectionAccessPathPart(pathParts[partIndex])) { List <Expression> statementsToAdd; (currNodeExpression, currNodeType, statementsToAdd) = BuildExpandingOfCollectionAccessPart(currNodeExpression, currNodeType, pathParts[partIndex]); statements.AddRange(statementsToAdd); } else if (TemplateDescriptionHelper.IsArrayPathPart(pathParts[partIndex])) { var statementsToAdd = BuildExpandingOfArrayPart(currNodeExpression, currNodeType, valueToSetExpression, pathParts.Skip(partIndex + 1).ToArray()); statements.AddRange(statementsToAdd); return(statements); } else if (!TypeCheckingHelper.IsNullable(currNodeType) && partIndex != pathParts.Length - 1) { statements.Add(ExpressionPrimitives.CreateValueInitStatement(currNodeExpression, currNodeType)); } } statements.Add(ExpressionPrimitives.AssignWithTypeCheckings(currNodeExpression, currNodeType, valueToSetExpression)); return(statements); }
public (ExcelTemplatePath pathToEnumerable, ExcelTemplatePath relativePathToItem) SplitForEnumerableExpansion() { if (!HasArrayAccess) { throw new BaseExcelSerializationException($"Expression needs enumerable expansion but has no part with '[]' or '[#]' (path - '{RawPath}')"); } var pathToEnumerableLength = PartsWithIndexers.TakeWhile(x => !TemplateDescriptionHelper.IsArrayPathPart(x)).Count() + 1; var pathToEnumerable = new ExcelTemplatePath(string.Join(".", PartsWithIndexers.Take(pathToEnumerableLength))); var relativePathToItem = new ExcelTemplatePath(string.Join(".", PartsWithIndexers.Skip(pathToEnumerableLength))); return(pathToEnumerable, relativePathToItem); }
private static (bool succeed, object result) TryExtractChildObject([NotNull] object model, [NotNull, ItemNotNull] string[] pathParts, int pathPartIndex) { if (pathPartIndex == pathParts.Length) { return(true, model); } if (!TryExtractDirectChild(model, pathParts[pathPartIndex], out var currentChild)) { return(false, null); } if (currentChild == null) { return(true, null); } if (TemplateDescriptionHelper.IsArrayPathPart(pathParts[pathPartIndex])) { if (!TypeCheckingHelper.IsEnumerable(currentChild.GetType())) { throw new ObjectPropertyExtractionException($"Trying to extract enumerable from non-enumerable property {string.Join(".", pathParts)}"); } var resultList = new List <object>(); foreach (var element in ((IEnumerable)currentChild).Cast <object>()) { if (element == null) { resultList.Add(null); } else { var(succeed, result) = TryExtractChildObject(element, pathParts, pathPartIndex + 1); if (!succeed) { return(false, result); } resultList.Add(result); } } return(true, resultList.ToArray()); } return(TryExtractChildObject(currentChild, pathParts, pathPartIndex + 1)); }
public static Type ExtractChildObjectTypeFromPath([NotNull] Type modelType, [NotNull] ExcelTemplatePath path) { var currType = modelType; foreach (var part in path.PartsWithIndexers) { var childPropertyType = ExtractPropertyInfo(currType, part).PropertyType; if (TemplateDescriptionHelper.IsCollectionAccessPathPart(part)) { if (TypeCheckingHelper.IsDictionary(childPropertyType)) { var(keyType, valueType) = TypeCheckingHelper.GetDictionaryGenericTypeArguments(childPropertyType); TemplateDescriptionHelper.ParseCollectionIndexerOrThrow(TemplateDescriptionHelper.GetCollectionAccessPathPartIndex(part), keyType); currType = valueType; } else if (TypeCheckingHelper.IsIList(childPropertyType)) { TemplateDescriptionHelper.ParseCollectionIndexerOrThrow(TemplateDescriptionHelper.GetCollectionAccessPathPartIndex(part), typeof(int)); currType = TypeCheckingHelper.GetEnumerableItemType(childPropertyType); } else { throw new ObjectPropertyExtractionException($"Not supported collection type {childPropertyType}"); } } else if (TemplateDescriptionHelper.IsArrayPathPart(part)) { if (TypeCheckingHelper.IsIList(childPropertyType)) { currType = TypeCheckingHelper.GetIListItemType(childPropertyType); } else { throw new ObjectPropertyExtractionException($"Not supported collection type {childPropertyType}"); } } else { currType = childPropertyType; } } return(currType); }