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); }
private static bool TryExtractDirectChild([NotNull] object model, [NotNull] string pathPart, out object child) { child = null; if (TemplateDescriptionHelper.IsCollectionAccessPathPart(pathPart)) { var name = TemplateDescriptionHelper.GetCollectionAccessPathPartName(pathPart); var key = TemplateDescriptionHelper.GetCollectionAccessPathPartIndex(pathPart); if (!TryExtractCurrentChildPropertyInfo(model, name, out var collectionPropertyInfo)) { return(false); } if (TypeCheckingHelper.IsDictionary(collectionPropertyInfo.PropertyType)) { var indexer = TemplateDescriptionHelper.ParseCollectionIndexerOrThrow(key, TypeCheckingHelper.GetDictionaryGenericTypeArguments(collectionPropertyInfo.PropertyType).keyType); var dict = collectionPropertyInfo.GetValue(model, null); if (dict == null) { return(true); } child = ((IDictionary)dict)[indexer]; return(true); } if (TypeCheckingHelper.IsIList(collectionPropertyInfo.PropertyType)) { var indexer = (int)TemplateDescriptionHelper.ParseCollectionIndexerOrThrow(key, typeof(int)); var list = collectionPropertyInfo.GetValue(model, null); if (list == null) { return(true); } child = ((IList)list)[indexer]; return(true); } throw new ObjectPropertyExtractionException($"Unexpected child type: expected dictionary or array (pathPath='{pathPart}'), but model is '{collectionPropertyInfo.PropertyType}' in '{model.GetType()}'"); } if (!TryExtractCurrentChildPropertyInfo(model, pathPart, out var propertyInfo)) { return(false); } child = propertyInfo.GetValue(model, null); return(true); }