Exemplo n.º 1
0
        private ToolStripMenuItem[] BuildOperationTree(IEnumerable <KeyValuePair <string, MethodInfo> > catalogMiPairList)
        {
            List <ToolStripMenuItem> res = new List <ToolStripMenuItem>();
            SortedDictionary <String, List <KeyValuePair <String, MethodInfo> > > catalogDic = new SortedDictionary <string, List <KeyValuePair <String, MethodInfo> > >();
            SortedDictionary <String, MethodInfo> operationItem = new SortedDictionary <string, MethodInfo>();

            foreach (KeyValuePair <string, MethodInfo> pair in catalogMiPairList)
            {
                if (String.IsNullOrEmpty(pair.Key))
                {  //this is an operation
                    operationItem.Add(pair.Value.ToString(), pair.Value);
                }
                else
                {  //this is a category
                    int    index = pair.Key.IndexOf('|');
                    String category;
                    String subcategory;
                    if (index == -1)
                    {  //There is no sub category
                        category    = pair.Key;
                        subcategory = string.Empty;
                    }
                    else
                    {  //There are sub categories
                        category    = pair.Key.Substring(0, index);
                        subcategory = pair.Key.Substring(index + 1, pair.Key.Length - index - 1);
                    }

                    if (!catalogDic.ContainsKey(category))
                    {
                        catalogDic.Add(category, new List <KeyValuePair <String, MethodInfo> >());
                    }
                    catalogDic[category].Add(new KeyValuePair <String, MethodInfo>(subcategory, pair.Value));
                }
            }

            #region Add catalogs to the menu
            foreach (String catalog in catalogDic.Keys)
            {
                ToolStripMenuItem catalogMenuItem = new ToolStripMenuItem();
                catalogMenuItem.Text = catalog;
                catalogMenuItem.DropDownItems.AddRange(BuildOperationTree(catalogDic[catalog]));
                res.Add(catalogMenuItem);
            }
            #endregion

            #region Add Methods to the menu
            foreach (MethodInfo mi in operationItem.Values)
            {
                ToolStripMenuItem operationMenuItem = new ToolStripMenuItem();
                operationMenuItem.Size = new Size(152, 22);

                Type[] genericArgs = mi.GetGenericArguments();

                String genericArgString = genericArgs.Length > 0 ?
                                          String.Format(
                    "<{0}>",
                    String.Join(",", Array.ConvertAll <Type, String>(
                                    genericArgs,
                                    System.Convert.ToString)))
                   : string.Empty;

                operationMenuItem.Text = String.Format(
                    "{0}{1}({2})",
                    mi.Name.Substring(0, 1).Equals("_") ? mi.Name.Substring(1, mi.Name.Length - 1) : mi.Name, //remove leading underscore
                    genericArgString,
                    String.Join(",", System.Array.ConvertAll <ParameterInfo, String>(mi.GetParameters(), delegate(ParameterInfo pi) { return(pi.Name); })));

                //This is necessary to handle delegate with a loop
                //Cause me lots of headache before reading the article on
                //http://decav.com/blogs/andre/archive/2007/11/18/wtf-quot-problems-quot-with-anonymous-delegates-linq-lambdas-and-quot-foreach-quot-or-quot-for-quot-loops.aspx
                //I wishes MSFT handle this better
                MethodInfo methodInfoRef = mi;

                operationMenuItem.Click += delegate
                {
                    Object[] paramList = null;

                    while (true)
                    {
                        //Get the parameters for the method
                        //this pop up an input dialog and ask for user input
                        paramList = ParameterInputDialog.GetParams(methodInfoRef, paramList);

                        if (paramList == null)
                        {
                            break;                        //user click cancel on the input dialog
                        }
                        //create an operation from the specific methodInfo and parameter list
                        Operation operation = new Operation(methodInfoRef, paramList);
                        try
                        {
                            PushOperation(operation);
                            break;
                        }
                        catch (Exception expt)
                        {
                            MessageBox.Show((expt.InnerException ?? expt).Message);

                            //special case, then there is no parameter and the method throw an exception
                            //break the loop
                            if (methodInfoRef.GetParameters().Length == 0)
                            {
                                break;
                            }
                        }
                    }
                };
                res.Add(operationMenuItem);
            }
            #endregion

            return(res.ToArray());
        }