Exemple #1
0
        //This function is pretty recursive
        //Indent = how many spaces before text
        //Add dictionary material support and then we guchi and never need to touch this again, just add attributes!
        //Example includes: listings[id],listinggroups
        public static bool List <T>(T element, bool verbose, string[] includes, string[] filterStrings = null, int length = int.MaxValue, int indents = 0)
        {
            //Parse the includes formatting strings. Key = Current Primary element. Tuple<lenofpelementifenumerable, subincludes>
            //Format: (currentElementName, (subIncludes, lenToList, filterString)
            Dictionary <string, Tuple <string[], int, string[]> > subIncludes = new Dictionary <string, Tuple <string[], int, string[]> >();

            if (includes != null)
            {
                Dictionary <string, string[]> subIncludesTmp = ParseSearchStringToDictionary(includes);
                //TODO Need to manage when filter string is null
                Dictionary <string, string[]> filterStringsTmp = ParseSearchStringToDictionary(filterStrings);
                //Reformat includesDict to include specified length
                foreach (string key in subIncludesTmp.Keys)
                {
                    string[] primaryInfo = key.Split(':');
                    string   primaryKey  = primaryInfo[0];
                    int      sublength   = (primaryInfo.Length > 1) ? Int32.Parse(primaryInfo[1]) : length;

                    string[] filterString;
                    //Since etsy objects will NEVER have a comparison done on them directly, we dont have to worry about reformatting any primary keys
                    //that may have a comparison sign in them
                    if (!filterStringsTmp.TryGetValue(primaryKey, out filterString))
                    {
                        filterString = null;
                    }

                    Tuple <string[], int, string[]> keyInfo = new Tuple <string[], int, string[]>(subIncludesTmp[key], sublength, filterString);
                    subIncludes.Add(primaryKey, keyInfo);
                }
            }

            Action <Tuple <PropertyInfo, ListableAttribute> > listElements = (propertyAttribute) =>
            {
                PropertyInfo      property  = propertyAttribute.Item1;
                ListableAttribute attribute = propertyAttribute.Item2;
                //If included, check if ienumerable or not
                bool isEnumerable = typeof(System.Collections.IEnumerable).IsAssignableFrom(property.PropertyType) && property.PropertyType != typeof(string);
                if (isEnumerable)
                {
                    //Set length for this
                    length = subIncludes[attribute.Name].Item2;
                    //Print header
                    string title = string.Format("{0}:", attribute.Name);
                    Console.WriteLine(title.PadLeft(title.Length + indents));
                    //Manage when stop listing
                    int i = 0;
                    System.Collections.IEnumerator enumerator = ((System.Collections.IEnumerable)(property.GetValue(element))).GetEnumerator();
                    bool hasNext = enumerator.MoveNext();
                    while (hasNext)
                    {
                        if (Filter(enumerator.Current, subIncludes[attribute.Name].Item3))
                        {
                            List(enumerator.Current, verbose, subIncludes[attribute.Name].Item1, filterStrings: subIncludes[attribute.Name].Item3, indents: indents + 4);
                            //If there is another item to print, put a spacer line in between them
                            if (hasNext && i != length - 1)
                            {
                                Console.WriteLine();
                            }
                            //Check if list is over
                            i++;
                            if (i >= length)
                            {
                                break;
                            }
                        }
                        hasNext = enumerator.MoveNext();
                    }
                }
                else
                {
                    //Works fine until we get a non array non basic data type passed in (Like Product or Material)
                    string toPrint = string.Format("{0}: {1}\n", attribute.Name, property.GetValue(element));
                    toPrint = toPrint.PadLeft(toPrint.Length + indents);
                    Console.Write(toPrint);
                }
            };


            //Get properties that are listable
            MemberInfo[] properties = element.GetType().GetProperties();
            properties = properties.Where(p => p.CustomAttributes.Any(a => a.AttributeType == typeof(ListableAttribute))).ToArray();

            //Create list of attributes for those properties
            List <Tuple <PropertyInfo, ListableAttribute> > attributes = new List <Tuple <PropertyInfo, ListableAttribute> >();

            foreach (PropertyInfo property in properties)
            {
                ListableAttribute attribute = (ListableAttribute)Attribute.GetCustomAttribute(property, typeof(ListableAttribute));
                attribute.Name = attribute.Name ?? property.Name.ToLower();
                attributes.Add(new Tuple <PropertyInfo, ListableAttribute>(property, attribute));
            }

            //Do default properties then take out of list so as to not be repeated
            Tuple <PropertyInfo, ListableAttribute>[] defaults = attributes.FindAll(t => t.Item2.Default).ToArray();
            foreach (var def in defaults)
            {
                listElements(def);
                attributes.Remove(def);
            }

            //Iterate over desired
            //I am iterating over keys instead of properties because I want things to be listed in the order they are formated in the includes string
            foreach (string key in subIncludes.Keys)
            {
                Tuple <PropertyInfo, ListableAttribute> propertyAttribute = attributes.Find(t => t.Item2.Name.Equals(key));
                if (propertyAttribute != null)
                {
                    ListableAttribute attribute = propertyAttribute.Item2;
                    //Use method supplied in attribute
                    if (attribute.CallbackClass != null)
                    {
                        MethodInfo methodInfo = attribute.CallbackClass.GetMethod(attribute.CallbackMethodName, BindingFlags.Public | BindingFlags.Static);
                        if (methodInfo != null)
                        {
                            //These parameters should work for any method supplied in an attribute, it is just required
                            //I should probably add a check to make sure, but I don't want to so I just won't mess it up for now
                            //since I am the only one using this
                            object[] parameters = { element, propertyAttribute, subIncludes[attribute.Name], indents };
                            methodInfo = methodInfo.MakeGenericMethod(element.GetType());
                            methodInfo.Invoke(null, parameters);
                        }
                        else
                        {
                            Console.WriteLine("Supplied callback method in class {0} name {1} does not exist or is not public and static", attribute.CallbackClass.GetType().ToString(), attribute.CallbackMethodName);
                        }
                    }
                    //Use this default list implementation
                    else
                    {
                        listElements(propertyAttribute);
                    }
                }
            }

            return(false);
        }
Exemple #2
0
        //Indent = how many spaces before text
        //Add dictionary material support and then we guchi and never need to touch this again, just add attributes!
        public static void List <T>(T element, bool verbose, string includes, int length = int.MaxValue, int indents = 0)
        {
            //Parse the includes formatting strings. Key = Current Primary element. Tuple<lenofpelementifenumerable, subincludes>
            Dictionary <string, string[]> subIncludes = new Dictionary <string, string[]>();

            if (includes != null)
            {
                //Finds square bracket sections and seperate them from the primary key
                Regex reg = new Regex(@"\[(.*)\]");

                //Splits into outermost comma seperated values, and lists those seperately
                //List doesn't list groups of things, so this seperates them into single items to list those
                Regex    reg2        = new Regex(@"[\w:]+(\[+.*?\]+)*");
                string[] allIncludes = (string.IsNullOrEmpty(includes)) ? null : reg.Matches(includes.ToLower()).Cast <Match>().Select(m => m.Value).ToArray();
                if (allIncludes.Length > 1)
                {
                    foreach (string include in allIncludes)
                    {
                        List(element, verbose, include, indents: indents);
                    }
                }

                foreach (string include in allIncludes)
                {
                    Match match = reg.Match(include);
                    if (match != null)
                    {
                        string   primaryKey  = include.Remove(match.Index, match.Length);
                        string[] primaryInfo = primaryKey.Split(':');
                        primaryKey = primaryInfo[0];
                        length     = (primaryInfo.Length > 1) ? Int32.Parse(primaryInfo[1]) : length;
                        string newIncludes = match.Groups[1].Value;

                        //splitting based on comma doesn't work, split based off other regex expression
                        string[] sub = (string.IsNullOrEmpty(newIncludes)) ? null : reg2.Matches(newIncludes).Cast <Match>().Select(m => m.Value).ToArray();
                        subIncludes.Add(primaryKey, sub);
                    }
                    else
                    {
                        subIncludes.Add(include, null);
                    }
                }
            }

            Action <Tuple <PropertyInfo, ListableAttribute> > listElements = (propertyAttribute) =>
            {
                PropertyInfo      property  = propertyAttribute.Item1;
                ListableAttribute attribute = propertyAttribute.Item2;
                //If included, check if ienumerable or not
                bool isEnumerable = typeof(System.Collections.IEnumerable).IsAssignableFrom(property.PropertyType) && property.PropertyType != typeof(string);
                if (isEnumerable)
                {
                    //Print header
                    string title = string.Format("{0}:", attribute.Name);
                    Console.WriteLine(title.PadLeft(title.Length + indents));
                    //Manage when stop listing
                    int i = 0;
                    System.Collections.IEnumerator enumerator = ((System.Collections.IEnumerable)(property.GetValue(element))).GetEnumerator();
                    bool hasNext = enumerator.MoveNext();
                    while (hasNext)
                    {
                        List(enumerator.Current, verbose, subIncludes[attribute.Name], indents: indents + 4);
                        //If there is another item to print, put a spacer line in between them
                        if (hasNext && i != length - 1)
                        {
                            Console.WriteLine();
                        }
                        //Check if list is over
                        i++;
                        if (i >= length)
                        {
                            break;
                        }
                        hasNext = enumerator.MoveNext();
                    }
                }
                else
                {
                    //Works fine until we get a non array non basic data type passed in (Like Product or Material)
                    string toPrint = string.Format("{0}: {1}\n", attribute.Name, property.GetValue(element));
                    toPrint = toPrint.PadLeft(toPrint.Length + indents);
                    Console.Write(toPrint);
                }
            };


            //Get properties that are listable
            MemberInfo[] properties = element.GetType().GetProperties();
            properties = properties.Where(p => p.CustomAttributes.Any(a => a.AttributeType == typeof(ListableAttribute))).ToArray();

            //Create list of attributes for those properties
            List <Tuple <PropertyInfo, ListableAttribute> > attributes = new List <Tuple <PropertyInfo, ListableAttribute> >();

            foreach (PropertyInfo property in properties)
            {
                ListableAttribute attribute = (ListableAttribute)Attribute.GetCustomAttribute(property, typeof(ListableAttribute));
                attribute.Name = attribute.Name ?? property.Name.ToLower();
                attributes.Add(new Tuple <PropertyInfo, ListableAttribute>(property, attribute));
            }

            //Do default properties then take out of list so as to not be repeated
            Tuple <PropertyInfo, ListableAttribute>[] defaults = attributes.FindAll(t => t.Item2.Default).ToArray();
            foreach (var def in defaults)
            {
                listElements(def);
                attributes.Remove(def);
            }

            //Iterate over desired
            //I am iterating over keys instead of properties because I want things to be listed in the order they are formated in the includes string
            foreach (string key in subIncludes.Keys)
            {
                Tuple <PropertyInfo, ListableAttribute> propertyAttribute = attributes.Find(t => t.Item2.Name.Equals(key));
                if (propertyAttribute != null)
                {
                    ListableAttribute attribute = propertyAttribute.Item2;
                    //Use method supplied in attribute
                    if (attribute.CallbackClass != null)
                    {
                        MethodInfo methodInfo = attribute.CallbackClass.GetMethod(attribute.CallbackMethodName, BindingFlags.Public | BindingFlags.Static);
                        if (methodInfo != null)
                        {
                            //These parameters should work for any method supplied in an attribute, it is just required
                            //I should probably add a check to make sure, but I don't want to so I just won't mess it up for now
                            //since I am the only one using this
                            object[] parameters = { element, propertyAttribute, subIncludes[attribute.Name], indents };
                            methodInfo = methodInfo.MakeGenericMethod(element.GetType());
                            methodInfo.Invoke(null, parameters);
                        }
                        else
                        {
                            Console.WriteLine("Supplied callback method in class {0} name {1} does not exist or is not public and static", attribute.CallbackClass.GetType().ToString(), attribute.CallbackMethodName);
                        }
                    }
                    //Use this default list implementation
                    else
                    {
                        listElements(propertyAttribute);
                    }
                }
            }
        }