public static Func <ChainNode, IEnumerable <MemberInfo> > ComposeLeafRule(ChainNode root)
 {
     return((node) =>
     {
         var filteredProperties = new List <MemberInfo>();
         var path = ChainNodeTree.FindLinkedRootKeyPath(node);
         var n = default(ChainNode);
         if (path.Length == 0)
         {
             n = root;
         }
         else
         {
             if (ChainNodeTree.FindNode(root, path, out ChainMemberNode c))
             {
                 n = c;
             }
         }
         if (n != default(ChainNode))
         {
             var type = n.Type;
             foreach (var child in n.Children)
             {
                 var propertyName = child.Key;
                 var propertyInfo = type.GetProperty(propertyName);
                 filteredProperties.Add(propertyInfo);
             }
         }
         return filteredProperties;
     });
 }
 private static object CloneItem(object sourceItem, ChainNode parentNode, IEnumerable <ChainMemberNode> nodes, Func <ChainNode, IEnumerable <MemberInfo> > leafRule)
 {
     if (sourceItem == null)
     {
         return(null);
     }
     else
     {
         var type     = sourceItem.GetType();
         var typeInfo = type.GetTypeInfo();
         if (sourceItem is string sourceString)
         {
             return(new String(sourceString.ToCharArray())); // String.Copy((string)sourceItem) absent in standard
         }
         else if (typeInfo.IsValueType)
         {
             if (nodes.Count() > 0)
             {
                 throw new InvalidOperationException($"It is impossible to clone value type's '{type.FullName}' instance specifing includes '{string.Join(", ", nodes.Select(e => e.MemberName))}' . Value type's instance can be cloned only entirely!");
             }
             return(sourceItem);
         }
         else if (typeInfo.IsClass)
         {
             var constructor     = typeInfo.DeclaredConstructors.First(e => e.GetParameters().Count() == 0);
             var destinationItem = constructor.Invoke(null);
             CopyNodes(sourceItem, destinationItem, parentNode, nodes, leafRule);
             return(destinationItem);
         }
         else
         {
             throw new InvalidOperationException($"Clonning of type '{type.FullName}' is not supported");
         }
     }
 }
        private static int AddLevelRecursive(ChainNode root, ChainMemberNode[] parents, int number, Expression inExpression, out Expression outExpression)
        {
            var @value = number;
            var node   = parents.Length == 0 ? root : parents[parents.Length - 1];

            outExpression = null;
            foreach (var childPair in node.Children)
            {
                var memberNode = childPair.Value;

                var modifiedParents = new ChainMemberNode[parents.Length + 1];
                parents.CopyTo(modifiedParents, 0);
                modifiedParents[parents.Length] = memberNode;

                if (memberNode.Children.Count != 0)
                {
                    @value       = AddLevelRecursive(root, modifiedParents, @value, inExpression, out outExpression);
                    inExpression = outExpression;
                }
                else
                {
                    @value       = AddMember(root, modifiedParents, @value, inExpression, out outExpression);
                    inExpression = outExpression;
                }
            }
            return(@value);
        }
        public static ChainMemberNode AddChild(this ChainNode node, FieldInfo fieldInfo)
        {
            var expression = node.Type.CreateFieldLambda(fieldInfo);
            var child      = new ChainMemberNode(fieldInfo.FieldType, expression, fieldInfo.Name, isEnumerable: false, node);

            node.Children.Add(fieldInfo.Name, child);
            return(child);
        }
Exemple #5
0
 public ChainMemberNode(Type type, LambdaExpression expression, string memberName, bool isEnumerable, ChainNode parent)
     : base(type)
 {
     Expression   = expression;
     MemberName   = memberName;
     IsEnumerable = isEnumerable;
     Parent       = parent;
 }
        public static ChainMemberNode AddChild(this ChainNode node, PropertyInfo propertyInfo)
        {
            var expression = node.Type.CreatePropertyLambda(propertyInfo);
            var child      = new ChainMemberNode(propertyInfo.PropertyType, expression, propertyInfo.Name, isEnumerable: false, node);

            node.Children.Add(propertyInfo.Name, child);
            return(child);
        }
        public static IReadOnlyCollection <Type> ListLeafTypes(this ChainNode node)
        {
            var nodes = node.Children.Values;
            var types = new List <Type>();

            ListLeafTypesRecursive(nodes, types);
            return(types);
        }
        private static int AddMember(ChainNode root, ChainMemberNode[] parents, int number, Expression inExpression, out Expression outExpression)
        {
            bool isRoot = true;

            outExpression = null;
            if (parents.Length == 0)
            {
                throw new Exception("Impossible situation");
            }
            var head = root;

            foreach (var p in parents)
            {
                MethodInfo includeMethodInfo = null;
                var        isEnumerable      = p.IsEnumerable;
                if (isRoot)
                {
                    if (isEnumerable)
                    {
                        Type       rootChainType            = typeof(Chain <>).MakeGenericType(root.Type);
                        MethodInfo includeGenericMethodInfo = rootChainType.GetTypeInfo().GetDeclaredMethod(nameof(Chain <object> .IncludeAll));
                        includeMethodInfo = includeGenericMethodInfo.MakeGenericMethod(p.Type);
                    }
                    else
                    {
                        Type       rootChainType            = typeof(Chain <>).MakeGenericType(root.Type);
                        MethodInfo includeGenericMethodInfo = rootChainType.GetTypeInfo().GetDeclaredMethod(nameof(Chain <object> .Include));
                        includeMethodInfo = includeGenericMethodInfo.MakeGenericMethod(p.Type);
                    }
                    isRoot = false;
                }
                else
                {
                    if (isEnumerable)
                    {
                        Type       rootChainType            = typeof(ThenChain <,>).MakeGenericType(root.Type, head.Type);
                        MethodInfo includeGenericMethodInfo = rootChainType.GetTypeInfo().GetDeclaredMethod(nameof(ThenChain <object, object> .ThenIncludeAll));
                        includeMethodInfo = includeGenericMethodInfo.MakeGenericMethod(p.Type);
                    }
                    else
                    {
                        Type       rootChainType            = typeof(ThenChain <,>).MakeGenericType(root.Type, head.Type);
                        MethodInfo includeGenericMethodInfo = rootChainType.GetTypeInfo().GetDeclaredMethod(nameof(ThenChain <object, object> .ThenInclude));
                        includeMethodInfo = includeGenericMethodInfo.MakeGenericMethod(p.Type);
                    }
                }
                var        lambda = p.Expression;
                var        name   = p.MemberName;
                Expression pExp   = Expression.Constant(name, typeof(string));
                var        methodCallExpression = Expression.Call(inExpression, includeMethodInfo, new[] { lambda, pExp });
                inExpression = methodCallExpression;

                isRoot = false;
                head   = p;
            }
            outExpression = inExpression;
            return(number + 1);
        }
        public static ChainMemberNode AddChild(this ChainNode node, string memberName)
        {
            var propertyInfo = node.Type.GetProperty(memberName);

            if (propertyInfo != null)
            {
                return(AddChild(node, propertyInfo));
            }
            else
            {
                var fieldInfo = node.Type.GetField(memberName);
                return(AddChild(node, fieldInfo));
            }
        }
        public static bool HasLeafs(this ChainNode node)
        {
            bool @value = false;

            foreach (var n in node.Children.Values)
            {
                if (n.Children.Count() == 0)
                {
                    @value = true;
                    break;
                }
            }
            return(@value);
        }
Exemple #11
0
        private static ChainMemberNode AddIfAbsent(
            ChainNode parent,
            LambdaExpression lambdaExpression,
            string memberName,
            Type navigationType,
            Type navigationEnumerableType,
            bool isEnumerable
            )
        {
            var dictionary = parent.Children;

            if (memberName != null)
            {
                if (!dictionary.TryGetValue(memberName, out ChainMemberNode node))
                {
                    node = new ChainMemberNode(navigationType, lambdaExpression, memberName, isEnumerable, parent);
                    dictionary.Add(memberName, node);
                }
                return(node);
            }
            else
            {
                if (lambdaExpression.Body is MemberExpression)
                {
                    var memberInfo = ((MemberExpression)lambdaExpression.Body).Member;
                    var name       = memberInfo.Name;
                    if (!dictionary.TryGetValue(name, out ChainMemberNode node))
                    {
                        node = new ChainMemberNode(navigationType, lambdaExpression, name, isEnumerable, parent);
                        dictionary.Add(name, node);
                    }
                    return(node);
                }
                else if (lambdaExpression.Body is MethodCallExpression)
                {
                    var methodInfo = ((MethodCallExpression)lambdaExpression.Body).Method;
                    var name       = methodInfo.Name;
                    if (!dictionary.TryGetValue(name, out ChainMemberNode node))
                    {
                        node = new ChainMemberNode(navigationType, lambdaExpression, name, isEnumerable, parent);
                        dictionary.Add(name, node);
                    }
                    return(node);
                }
                else
                {
                    throw new NotSupportedException("Not supported type of expression: neither member, neither method call");
                }
            }
        }
 internal static void CopyNodes(
     object source,
     object destination,
     ChainNode parentNode,
     IEnumerable <ChainMemberNode> nodes,
     Func <ChainNode, IEnumerable <MemberInfo> > leafRule)
 {
     if (source is Array sourceArray)
     {
         CopyArray(sourceArray, (Array)destination, sourceItem => CloneItem(sourceItem, parentNode, nodes, leafRule));
     }
     else if (source is IEnumerable enumerable && destination is IList destinationList)
     {
         CopyList(enumerable, destinationList, sourceItem => CloneItem(sourceItem, parentNode, nodes, leafRule));
     }
        public static Include <T> ComposeInclude <T>(this ChainNode root)
        {
            var  parents       = new ChainMemberNode[0];
            var  entityType    = root.Type;
            Type rootChainType = typeof(Chain <>).MakeGenericType(entityType);
            ParameterExpression tParameterExpression = Expression.Parameter(rootChainType, "t");
            int         number       = AddLevelRecursive(root, parents, 0, tParameterExpression, out Expression outExpression);
            Include <T> @destination = null;

            if (outExpression != null)
            {
                var lambdaExpression = Expression.Lambda <Include <T> >(outExpression, new[] { tParameterExpression });
                @destination = lambdaExpression.Compile();
            }
            return(@destination);
        }
        public static void AppendLeafs(this ChainNode node, Func <ChainNode, IEnumerable <MemberInfo> > leafRule = null)
        {
            if (leafRule == null)
            {
                leafRule = LeafRuleManager.Default;
            }
            foreach (var n in node.Children.Values)
            {
                AppendLeafs(n, leafRule);
            }
            var hasLeafs = node.HasLeafs();

            if (!hasLeafs)
            {
                var members = leafRule(node);
                foreach (var memberInfo in members)
                {
                    node.AddChild(memberInfo.Name);
                }
            }
        }
Exemple #15
0
 public static IReadOnlyCollection <string> ListXPaths(ChainNode node) =>
 TreeExtensions.ListXPaths(meta, node);
Exemple #16
0
 public static IReadOnlyCollection <ChainNode> ListLeafPaths(ChainNode node) =>
 TreeExtensions.ListLeafPaths(meta, node);
Exemple #17
0
 public static ChainNode Merge(ChainNode node1, ChainNode node2) =>
 TreeExtensions.Merge(meta, node1, node2);
Exemple #18
0
 public static bool IsSubTreeOf(ChainNode node1, ChainNode node2) =>
 TreeExtensions.IsSubTreeOf(meta, node1, node2);
Exemple #19
0
 public static bool IsEqualTo(ChainNode node1, ChainNode node2) =>
 TreeExtensions.IsEqualTo(meta, node1, node2);
Exemple #20
0
 public static string[] FindLinkedRootKeyPath(ChainNode node) =>
 TreeExtensions.FindLinkedRootKeyPath(meta, node);
Exemple #21
0
 public static bool FindNode(ChainNode root, string[] path, out ChainMemberNode node) =>
 TreeExtensions.FindNode(meta, root, path, out node);
 public static IReadOnlyCollection <string> ListXPaths(this ChainNode node)
 {
     return(ChainNodeTree.ListXPaths(node));
 }
        public static ChainMemberNode CloneChainMemberNode(this ChainMemberNode node, ChainNode parent)
        {
            var child = new ChainMemberNode(node.Type, node.Expression, /* node.MemberInfo,*/ node.MemberName, /*node.ChainMemberNodeExpressionType,*/ node.IsEnumerable, parent);

            parent.Children.Add(node.MemberName, child);
            return(child);
        }