{"id":904,"date":"2016-02-07T21:32:28","date_gmt":"2016-02-07T21:32:28","guid":{"rendered":"http:\/\/piatkosia.k4be.pl\/wordpress\/?p=904"},"modified":"2016-02-07T21:34:08","modified_gmt":"2016-02-07T21:34:08","slug":"904","status":"publish","type":"post","link":"https:\/\/piatkosia.k4be.pl\/wordpress\/2016\/02\/07\/904\/","title":{"rendered":"WPF\/C# &#8211; Generowanie menu przy u\u017cyciu mechanizmu refleksji"},"content":{"rendered":"<p style=\"text-align: justify;\">Tym razem co\u015b o programowaniu, bo dawno nie by\u0142o:)<\/p>\n<p style=\"text-align: justify;\">Refleksja jest znana z tego, \u017ce jest wolna jak dupa w\u0119\u017ca. Ale lubi\u0119 si\u0119 j\u0105 bawi\u0107 niemal tak samo, jak WMI.<br \/>\nPo prostu nadal mi to zionie magi\u0105. I sobie wymy\u015bli\u0142am, \u017ce spr\u00f3buj\u0119 u\u017cy\u0107 tego mechanizmu do generowania menu &#8222;w locie&#8221;.<\/p>\n<p style=\"text-align: justify;\"><!--more--><br \/>\nPostanowi\u0142am, \u017ce ka\u017cda klasa b\u0119dzie menu, a jej podklasy b\u0119d\u0105 funkcjami w danym menu. Ca\u0142o\u015b\u0107 wygl\u0105da nast\u0119puj\u0105co.<\/p>\n<pre class=\"brush: csharp; collapse: true\">\r\nusing System;\r\nusing System.Collections.Generic;\r\nusing System.Windows;\r\nusing System.Windows.Controls;\r\n\r\nnamespace MenuGeneratorSample\r\n{\r\n    public partial class MainWindow : Window\r\n    {\r\n        public MainWindow()\r\n        {\r\n            InitializeComponent();\r\n            mainMenu.IsMainMenu = true;\r\n            mainMenu.Items.Add(addClass(typeof(FirstClass)));\r\n            mainMenu.Items.Add(addClass(typeof(SecondClass)));\r\n\r\n        }\r\n        public static object GetNewObject(Type t)\r\n        {\r\n            try\r\n            {\r\n                var constructorInfo = t.GetConstructor(new Type[] { });\r\n                if (constructorInfo != null)\r\n                    return constructorInfo.Invoke(new object[] { });\r\n                else return null;\r\n            }\r\n            catch\r\n            {\r\n                return null;\r\n            }\r\n        }\r\n\r\n        public MenuItem addClass(Type classType)\r\n        {\r\n            var MissingMethods = typeof (Object).GetMethods();\r\n            List NotToAdd = new List();\r\n            foreach (var method in MissingMethods)\r\n            {\r\n                NotToAdd.Add(method.Name);\r\n            } \/\/aby nie dodatwa\u0142o ToString\u00f3w i innych gethashcode'\u00f3w\r\n            MenuItem menu = new MenuItem();\r\n            menu.Header = menu.Name = classType.Name;   \r\n            var methods = classType.GetMethods();\r\n            foreach (var method in methods)\r\n            {\r\n                if (NotToAdd.Contains(method.Name)) break;\r\n                MenuItem item = new MenuItem();\r\n                item.Header = item.Name = method.Name;\r\n                item.Click += delegate(object sender, RoutedEventArgs args) { method.Invoke(GetNewObject(classType), null); };\r\n                menu.Items.Add(item);\r\n            }\r\n            return menu;\r\n        }\r\n\r\n    }\r\n}\r\n<\/pre>\n<p style=\"text-align: justify;\">T\u0105 funkcj\u0119 powy\u017cej mo\u017cna przerobi\u0107, by zamiast typu pobiera\u0142a jaki\u015b obiekt. I wtedy zamiast classType.GetMethods() mieliby\u015bcie obiekt.GetType().GetMethods();, a zamiast null jako 2 parametr invoka mogliby\u015bcie da\u0107 tablic\u0119 obiekt\u00f3w (b\u0119d\u0105c\u0105 cz\u0119\u015bci\u0105 tego obiektu) kt\u00f3ra by\u0142aby parametrami do danej funkcji.<br \/>\nNale\u017ca\u0142oby jeszcze przy definicji funkcji w nawiasie doda\u0107 ten obiekt jako parametr. Tutaj jednak za\u0142o\u017cy\u0142am najprostszy przypadek. Powy\u017cej za\u0142o\u017cy\u0142am, \u017ce mainMenu to dodana do pliku xaml kontrolka typu menu. Aby przetestowa\u0107 t\u0105 funkcj\u0119 nale\u017cy doda\u0107 te dwie klasy (FirstClass i SecondClass). Mog\u0105 to by\u0107 klasy kt\u00f3re robi\u0105 cokolwiek. Rozwa\u017caj\u0105c najprostszy przypadek:<\/p>\n<pre class=\"brush: csharp; collapse: true\">\r\nusing System.Windows;\r\n\r\nnamespace MenuGeneratorSample\r\n{\r\n    public class FirstClass\r\n    {\r\n\r\n        public void FirstMethod()\r\n        {\r\n            MessageBox.Show(\"Pierwsza metoda z klasy FirstClass\");\r\n        }\r\n\r\n        public void SecondMethod()\r\n        {\r\n            MessageBox.Show(\"Druga metoda z klasy FirstClass\");\r\n        }\r\n        public void ThirdMethod()\r\n        {\r\n            MessageBox.Show(\"Trzecia metoda z klasy FirstClass\");\r\n        }\r\n    }\r\n}\r\n<\/pre>\n<p>I jeszcze druga:<\/p>\n<pre class=\"brush: csharp; collapse: true\">\r\nusing System.Windows;\r\n\r\nnamespace MenuGeneratorSample\r\n{\r\n    public class SecondClass\r\n    {\r\n        public void FirstMethod()\r\n        {\r\n            MessageBox.Show(\"Pierwsza metoda z klasy SecondClass\");\r\n        }\r\n\r\n        public void SecondMethod()\r\n        {\r\n            MessageBox.Show(\"Druga metoda z klasy SecondClass\");\r\n        }\r\n    }\r\n}\r\n<\/pre>\n<p style=\"text-align: justify;\">Foreach mo\u017ce si\u0119 r\u00f3\u017cnie zachowywa\u0107, wi\u0119c mo\u017ce by\u0107 lekki problem z zachowaniem kolejno\u015bci mi\u0119dzy wersjami kompilatora (tak wynika z dokumentacji) ale to jest na prawd\u0119 pomijalne.<\/p>\n<p style=\"text-align: justify;\">Je\u017celi nie chcecie dodawa\u0107 mo\u017cecie doda\u0107 wszystkie typy z assembly (Assembly.GetTypes() i do tego jaki\u015b foreach &#8211; zobaczy\u0107 co pomin\u0105\u0107 etc &#8211; pobawcie si\u0119 sami).<\/p>\n<p style=\"text-align: justify;\">Mo\u017cliwo\u015bci jest sporo- bawcie si\u0119 dobrze;)<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Tym razem co\u015b o programowaniu, bo dawno nie by\u0142o:) Refleksja jest znana z tego, \u017ce jest wolna jak dupa w\u0119\u017ca. Ale lubi\u0119 si\u0119 j\u0105 bawi\u0107<\/p>\n<div class=\"more-link-wrapper\"><a class=\"more-link\" href=\"https:\/\/piatkosia.k4be.pl\/wordpress\/2016\/02\/07\/904\/\">Lecim dalej<span class=\"screen-reader-text\">WPF\/C# &#8211; Generowanie menu przy u\u017cyciu mechanizmu refleksji<\/span> <i class=\"fas fa-angle-right\"><\/i><\/a><\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1,83,143],"tags":[211,244,243,241,242],"class_list":["post-904","post","type-post","status-publish","format-standard","hentry","category-bez-kategorii","category-c_sharp","category-wpf","tag-c","tag-code-behind","tag-menu","tag-refleksja","tag-wpf","entry"],"_links":{"self":[{"href":"https:\/\/piatkosia.k4be.pl\/wordpress\/wp-json\/wp\/v2\/posts\/904","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/piatkosia.k4be.pl\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/piatkosia.k4be.pl\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/piatkosia.k4be.pl\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/piatkosia.k4be.pl\/wordpress\/wp-json\/wp\/v2\/comments?post=904"}],"version-history":[{"count":2,"href":"https:\/\/piatkosia.k4be.pl\/wordpress\/wp-json\/wp\/v2\/posts\/904\/revisions"}],"predecessor-version":[{"id":906,"href":"https:\/\/piatkosia.k4be.pl\/wordpress\/wp-json\/wp\/v2\/posts\/904\/revisions\/906"}],"wp:attachment":[{"href":"https:\/\/piatkosia.k4be.pl\/wordpress\/wp-json\/wp\/v2\/media?parent=904"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/piatkosia.k4be.pl\/wordpress\/wp-json\/wp\/v2\/categories?post=904"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/piatkosia.k4be.pl\/wordpress\/wp-json\/wp\/v2\/tags?post=904"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}