Exemplo n.º 1
0
        public TOutput VisitProperties(TInput node, Func <TInput, TOutput> visit)
        {
            if (node == null)
            {
                return(default(TOutput));
            }

            Type type = node.GetType();

            PropertyInfo[] properties = ReflectionCache.GetReadWriteClassProperties(type);

            TOutput result = Clone ? (TOutput)Activator.CreateInstance(type) : default(TOutput);

            foreach (PropertyInfo prop in properties)
            {
                Type propType = prop.PropertyType;
                if (IgnoredProperties.Contains(prop.Name))
                {
                    continue;
                }
                else if (propType.IsValueType || propType == typeof(string) || propType == typeof(Regex))
                {
                    if (Clone)
                    {
                        prop.SetValue(result, prop.GetValue(node));
                    }
                }
                else if (typeof(TInput).IsAssignableFrom(propType))
                {
                    TOutput setValue = visit((TInput)prop.GetValue(node));
                    if (Clone)
                    {
                        prop.SetValue(result, setValue);
                    }
                }
                else if (propType.GetInterfaces().Contains(typeof(IEnumerable)))
                {
                    Type  itemType       = propType.GetGenericArguments()[0];
                    IList destCollection = null;
                    var   collection     = prop.GetValue(node);
                    if (collection != null)
                    {
                        IEnumerable <object> sourceCollection;
                        if (collection is IEnumerable <object> refCollection)
                        {
                            sourceCollection = refCollection;
                        }
                        else
                        {
                            sourceCollection = ((IEnumerable)collection).Cast <object>();
                        }

                        destCollection = (IList)Activator.CreateInstance(typeof(List <>).MakeGenericType(itemType));
                        foreach (object item in sourceCollection)
                        {
                            object destItem = item is TInput sourceItem
                                ? visit(sourceItem)
                                : item;

                            if (Clone)
                            {
                                destCollection.Add(destItem);
                            }
                        }
                    }
                    if (Clone)
                    {
                        prop.SetValue(result, destCollection);
                    }
                }
                else
                {
                    throw new NotImplementedException($"Property \"{prop}\" processing is not implemented via reflection");
                }
            }

            return(result);
        }
Exemplo n.º 2
0
        public int Compare(object node, object other)
        {
            if (node == null && other == null)
            {
                return(0);
            }
            else if (node != null && other == null)
            {
                return(1);
            }
            else if (node == null && other != null)
            {
                return(-1);
            }

            Type type1 = node.GetType();
            Type type2 = other.GetType();

            if (!(type1.GetInterfaces().Contains(typeof(IList)) && type2.GetInterfaces().Contains(typeof(IList))))
            {
                if (type1 != type2)
                {
                    return(type1.Name.CompareTo(type2.Name));
                }
            }

            int result          = 0;
            var type1Interfaces = type1.GetInterfaces();

            if (type1Interfaces.Contains(typeof(IComparable)))
            {
                var comparable1 = (IComparable)node;
                var comparable2 = (IComparable)other;
                result = comparable1.CompareTo(comparable2);
                if (result != 0)
                {
                    return(result);
                }
            }
            else if (type1 == typeof(Regex))
            {
                var comparable1 = (Regex)node;
                var comparable2 = (Regex)other;
                result = comparable1.ToString().CompareTo(comparable2.ToString());
                if (result != 0)
                {
                    return(result);
                }
            }
            else if (type1.IsSubclassOf(typeof(T)) || type1 == typeof(T))
            {
                PropertyInfo[] properties1 = ReflectionCache.GetReadWriteClassProperties(type1);
                PropertyInfo[] properties2 = ReflectionCache.GetReadWriteClassProperties(type2);

                if (properties1.Length != properties2.Length)
                {
                    return(properties1.Length - properties2.Length);
                }

                for (int i = 0; i < properties1.Length; i++)
                {
                    if (!IgnoredProperties.Contains(properties1[i].Name))
                    {
                        result = Compare(properties1[i].GetValue(node), properties2[i].GetValue(other));
                        if (result != 0)
                        {
                            return(result);
                        }
                    }
                }
            }
            else if (type1Interfaces.Contains(typeof(IList)))
            {
                var node1List = (IList)node;
                var node2List = (IList)other;

                if (node1List.Count != node2List.Count)
                {
                    return(node1List.Count - node2List.Count);
                }

                for (int i = 0; i < node1List.Count; i++)
                {
                    result = Compare(node1List[i], node2List[i]);
                    if (result != 0)
                    {
                        return(result);
                    }
                }
            }
            else
            {
                throw new NotImplementedException($"Type \"{type1}\" comparison is not implemented via reflection");
            }

            return(0);
        }