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); }
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); }
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); } } }
public static IReadOnlyCollection <string> ListXPaths(ChainNode node) => TreeExtensions.ListXPaths(meta, node);
public static IReadOnlyCollection <ChainNode> ListLeafPaths(ChainNode node) => TreeExtensions.ListLeafPaths(meta, node);
public static ChainNode Merge(ChainNode node1, ChainNode node2) => TreeExtensions.Merge(meta, node1, node2);
public static bool IsSubTreeOf(ChainNode node1, ChainNode node2) => TreeExtensions.IsSubTreeOf(meta, node1, node2);
public static bool IsEqualTo(ChainNode node1, ChainNode node2) => TreeExtensions.IsEqualTo(meta, node1, node2);
public static string[] FindLinkedRootKeyPath(ChainNode node) => TreeExtensions.FindLinkedRootKeyPath(meta, node);
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); }