Esempio n. 1
0
        private static bool TryExtractCurrentChildPropertyInfo([NotNull] object model, [NotNull] string pathPart, out PropertyInfo childPropertyInfo)
        {
            var propertyName = TemplateDescriptionHelper.GetPathPartName(pathPart);

            childPropertyInfo = model.GetType().GetProperty(propertyName);
            return(childPropertyInfo != null);
        }
        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);
        }
Esempio n. 3
0
        private static PropertyInfo ExtractPropertyInfo([NotNull] Type type, [NotNull] string pathPart)
        {
            var propertyName      = TemplateDescriptionHelper.GetPathPartName(pathPart);
            var childPropertyInfo = type.GetProperty(propertyName);

            if (childPropertyInfo == null)
            {
                throw new ObjectPropertyExtractionException($"Property with name '{propertyName}' not found in type '{type}'");
            }
            return(childPropertyInfo);
        }
 private ExcelTemplatePath(string rawPath)
 {
     if (!TemplateDescriptionHelper.IsCorrectModelPath(rawPath))
     {
         throw new ObjectPropertyExtractionException($"Invalid excel template path '{rawPath}'");
     }
     PartsWithIndexers       = rawPath.Split('.');
     PartsWithoutArrayAccess = PartsWithIndexers.Select(TemplateDescriptionHelper.GetArrayPathPartName).ToArray();
     RawPath                  = rawPath;
     HasArrayAccess           = PartsWithIndexers.Any(TemplateDescriptionHelper.IsArrayPathPart);
     HasPrimaryKeyArrayAccess = PartsWithIndexers.Any(TemplateDescriptionHelper.IsPrimaryArrayPathPart);
 }
        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);
        }
        public static ExcelTemplatePath FromRawExpression(string expression)
        {
            if (expression == null || !TemplateDescriptionHelper.IsCorrectAbstractValueDescription(expression))
            {
                throw new ObjectPropertyExtractionException($"Invalid description '{expression}'");
            }
            var parts = TemplateDescriptionHelper.GetDescriptionParts(expression);

            if (parts.Length != 3)
            {
                throw new ObjectPropertyExtractionException($"Invalid description '{expression}'");
            }
            return(new ExcelTemplatePath(parts[2]));
        }
Esempio n. 7
0
        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));
        }
Esempio n. 8
0
        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);
        }
Esempio n. 9
0
 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);
 }
        private static (Expression currNodeExpression, Type currNodeType, List <Expression> statements) BuildExpandingOfCollectionAccessPart([NotNull] Expression currNodeExpression, [NotNull] Type currNodeType, [NotNull] string part)
        {
            var statements = new List <Expression>();

            if (TypeCheckingHelper.IsDictionary(currNodeType))
            {
                statements.Add(ExpressionPrimitives.CreateValueInitStatement(currNodeExpression, currNodeType));

                var(dictKeyType, dictValueType) = TypeCheckingHelper.GetDictionaryGenericTypeArguments(currNodeType);
                var indexer = TemplateDescriptionHelper.ParseCollectionIndexerOrThrow(TemplateDescriptionHelper.GetCollectionAccessPathPartIndex(part), dictKeyType);

                var dictElementExpression = Expression.Property(currNodeExpression, "Item", Expression.Constant(indexer));

                statements.Add(ExpressionPrimitives.CreateDictValueInitStatement(currNodeExpression, dictKeyType, dictValueType, indexer));

                currNodeExpression = dictElementExpression;
                currNodeType       = dictValueType;
            }
            else if (currNodeType.IsArray)
            {
                var arrayItemType = currNodeType.GetElementType() ?? throw new ObjectPropertyExtractionException($"Array of type '{currNodeType}' has no item type");
                var indexer       = TemplateDescriptionHelper.ParseCollectionIndexerOrThrow(TemplateDescriptionHelper.GetCollectionAccessPathPartIndex(part), typeof(int));
                statements.Add(ExpressionPrimitives.CreateArrayExtendStatement(currNodeExpression, Expression.Constant((int)indexer + 1), arrayItemType));
                var arrayItemExpression = Expression.ArrayAccess(currNodeExpression, Expression.Constant(indexer));

                currNodeExpression = arrayItemExpression;
                currNodeType       = arrayItemType;

                statements.Add(ExpressionPrimitives.CreateValueInitStatement(currNodeExpression, currNodeType));
            }
            else
            {
                throw new ObjectPropertyExtractionException("Only dicts and arrays are supported as collections");
            }
            return(currNodeExpression, currNodeType, statements);
        }