// // ManagedAssemblyPanel.cs - provides a UWT Container with controls to edit managed assembly information for an ExecutableObjectModel // // Author: // Michael Becker // // Copyright (c) 2019-2020 Mike Becker's Software // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . using System; using System.Reflection; using System.Text; using MBS.Framework.UserInterface; using MBS.Framework.UserInterface.Controls; using MBS.Framework.UserInterface.Dialogs; using MBS.Framework.UserInterface.Layouts; namespace UniversalEditor.Plugins.Executable.UserInterface.Editors.Executable { /// /// Provides a UWT Container with controls to edit managed assembly information for an . /// public class ManagedAssemblyPanel : Container { private TextBox txtSearch = null; private ListView tvTypes = null; private DefaultTreeModel tmTypes = null; private TextBox txtSource = null; private ComboBox cboLanguage = null; private Assembly _Assembly = null; public Assembly Assembly { get { return _Assembly; } set { _Assembly = value; UpdateTypeList(); } } private void UpdateTypeList() { tmTypes.Rows.Clear(); Type[] types = null; try { types = _Assembly.GetTypes(); } catch (ReflectionTypeLoadException ex) { types = ex.Types; } for (int i = 0; i < types.Length; i++) { if (types[i] == null) continue; string[] nameParts = types[i].FullName.Split(new char[] { '.' }); bool nestedClass = false; while (nameParts[nameParts.Length - 1].Contains("+")) { // handle the case of nested classes nestedClass = true; Array.Resize(ref nameParts, nameParts.Length + 1); string[] p = nameParts[nameParts.Length - 2].Split(new char[] { '+' }); nameParts[nameParts.Length - 2] = p[0]; nameParts[nameParts.Length - 1] = p[1]; } TreeModelRow row = tmTypes.RecursiveCreateTreeModelRow(tmTypes.Columns[0], nameParts, new TreeModelRowColumn[] { new TreeModelRowColumn(tmTypes.Columns[1], "Namespace") }); if (nestedClass) row.ParentRow.RowColumns[1].Value = "Class"; row.RowColumns.Add(new TreeModelRowColumn(tmTypes.Columns[1], "Class")); SetupTypeTreeModelRow(row, types[i]); } } private void SetupTypeTreeModelRow(TreeModelRow row, Type type) { row.SetExtraData("item", type); BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly; TreeModelRow rowBaseTypes = new TreeModelRow(new TreeModelRowColumn[] { new TreeModelRowColumn(tmTypes.Columns[0], "Base Types") }); if (type.BaseType != null) { TreeModelRow rowBaseType = new TreeModelRow(new TreeModelRowColumn[] { new TreeModelRowColumn(tmTypes.Columns[0], type.BaseType.FullName) }); SetupTypeTreeModelRow(rowBaseType, type.BaseType); rowBaseTypes.Rows.Add(rowBaseType); } row.Rows.Add(rowBaseTypes); TreeModelRow rowDerivedTypes = new TreeModelRow(new TreeModelRowColumn[] { new TreeModelRowColumn(tmTypes.Columns[0], "Derived Types") }); row.Rows.Add(rowDerivedTypes); FieldInfo[] fields = type.GetFields(bindingFlags); for (int j = 0; j < fields.Length; j++) { TreeModelRow row2 = new TreeModelRow(new TreeModelRowColumn[] { new TreeModelRowColumn(tmTypes.Columns[0], fields[j]), new TreeModelRowColumn(tmTypes.Columns[1], "Field") }); row2.SetExtraData("item", fields[j]); row.Rows.Add(row2); } EventInfo[] events = type.GetEvents(bindingFlags); for (int j = 0; j < events.Length; j++) { TreeModelRow row2 = new TreeModelRow(new TreeModelRowColumn[] { new TreeModelRowColumn(tmTypes.Columns[0], events[j]), new TreeModelRowColumn(tmTypes.Columns[1], "Event") }); row2.SetExtraData("item", events[j]); row.Rows.Add(row2); } PropertyInfo[] props = type.GetProperties(bindingFlags); for (int j = 0; j < props.Length; j++) { TreeModelRow row2 = new TreeModelRow(new TreeModelRowColumn[] { new TreeModelRowColumn(tmTypes.Columns[0], props[j]), new TreeModelRowColumn(tmTypes.Columns[1], "Property") }); row2.SetExtraData("item", props[j]); row.Rows.Add(row2); } MethodInfo[] meths = type.GetMethods(bindingFlags); for (int j = 0; j < meths.Length; j++) { if (meths[j].IsSpecialName && (meths[j].Name.StartsWith("set_", StringComparison.OrdinalIgnoreCase) || meths[j].Name.StartsWith("get_", StringComparison.OrdinalIgnoreCase))) { // we can be REASONABLY sure that this is a property setter / getter, // and as we've already gotten all the properties, ignore it continue; } TreeModelRow row2 = new TreeModelRow(new TreeModelRowColumn[] { new TreeModelRowColumn(tmTypes.Columns[0], GetMethodTitle(meths[j])), new TreeModelRowColumn(tmTypes.Columns[1], "Method") }); row2.SetExtraData("item", meths[j]); row.Rows.Add(row2); } } private void tsbILSave_Click(object sender, EventArgs e) { MemberInfo t = tvTypes.SelectedRows[0].GetExtraData("item"); if (t == null) return; FileDialog dlg = new FileDialog(); dlg.Text = "Save Code File"; dlg.SelectedFileNames.Clear(); dlg.SelectedFileNames.Add(t.Name + Language.CodeFileExtension); if (dlg.ShowDialog() == DialogResult.OK) { } } public ManagedAssemblyPanel() { Layout = new BoxLayout(Orientation.Vertical); Container ctToolbarAndOthers = new Container(); ctToolbarAndOthers.Layout = new BoxLayout(Orientation.Horizontal); Toolbar tb = new Toolbar(); tb.Items.Add(new ToolbarItemButton("tsbILSave", StockType.Save, tsbILSave_Click)); ctToolbarAndOthers.Controls.Add(tb, new BoxLayout.Constraints(false, true)); cboLanguage = new ComboBox(); cboLanguage.Changed += cboLanguage_Changed; Type[] codeProviders = MBS.Framework.Reflection.GetAvailableTypes(new Type[] { typeof(CodeProvider) }); DefaultTreeModel tmLanguage = new DefaultTreeModel(new Type[] { typeof(string) }); /* tmLanguage.Rows.Add(new TreeModelRow(new TreeModelRowColumn[] { new TreeModelRowColumn(tmLanguage.Columns[0], "Raw Bytes") })); */ for (int i = 0; i < codeProviders.Length; i++) { CodeProvider codeProvider = (codeProviders[i].Assembly.CreateInstance(codeProviders[i].FullName) as CodeProvider); TreeModelRow row = new TreeModelRow(new TreeModelRowColumn[] { new TreeModelRowColumn(tmLanguage.Columns[0], codeProvider.Title) }); row.SetExtraData("provider", codeProvider); tmLanguage.Rows.Add(row); } if (tmLanguage.Rows.Count > 0) { cboLanguage.SelectedItem = tmLanguage.Rows[0]; } cboLanguage.ReadOnly = true; cboLanguage.Model = tmLanguage; ctToolbarAndOthers.Controls.Add(cboLanguage, new BoxLayout.Constraints(false, false)); Controls.Add(ctToolbarAndOthers, new BoxLayout.Constraints(false, true)); SplitContainer scLeftRight = new SplitContainer(Orientation.Vertical); scLeftRight.SplitterPosition = 250; txtSearch = new TextBox(); scLeftRight.Panel1.Layout = new BoxLayout(Orientation.Vertical); scLeftRight.Panel1.Controls.Add(txtSearch, new BoxLayout.Constraints(false, true)); tvTypes = new ListView(); tvTypes.SelectionChanged += tvTypes_SelectionChanged; tmTypes = new DefaultTreeModel(new Type[] { typeof(string), typeof(string) }); tvTypes.Model = tmTypes; tvTypes.Columns.Add(new ListViewColumnText(tmTypes.Columns[0], "Name")); tvTypes.Columns.Add(new ListViewColumnText(tmTypes.Columns[1], "Type")); scLeftRight.Panel1.Controls.Add(tvTypes, new BoxLayout.Constraints(true, true)); scLeftRight.Panel2.Layout = new BoxLayout(Orientation.Vertical); txtSource = new TextBox(); txtSource.Multiline = true; scLeftRight.Panel2.Controls.Add(txtSource, new BoxLayout.Constraints(true, true)); Controls.Add(scLeftRight, new BoxLayout.Constraints(true, true)); } void cboLanguage_Changed(object sender, EventArgs e) { CodeProvider provider = cboLanguage.SelectedItem.GetExtraData("provider"); Language = provider; } private CodeProvider _Language = CodeProvider.CSharp; public CodeProvider Language { get { return _Language; } set { _Language = value; tvTypes_SelectionChanged(this, EventArgs.Empty); } } private string GetAccessModifiersSourceCode(PropertyInfo mi) { return Language.GetAccessModifiers(mi); } private string GetAccessModifiersSourceCode(MethodInfo mi) { return Language.GetAccessModifiers(mi); } private string GetAccessModifiersSourceCode(FieldInfo mi) { return Language.GetAccessModifiers(mi); } private string GetAccessModifiersSourceCode(Type mi) { return Language.GetAccessModifiers(mi); } private string GetMethodTitle(MethodInfo mi) { StringBuilder sb = new StringBuilder(); string typeName = Language.GetTypeName(mi.ReturnType); sb.Append(mi.Name); sb.Append('('); sb.Append(')'); sb.Append(" : "); sb.Append(typeName); return sb.ToString(); } private void tvTypes_SelectionChanged(object sender, EventArgs e) { if (tvTypes.SelectedRows.Count == 0) return; object item = tvTypes.SelectedRows[0].GetExtraData("item"); if (item is Type) { Type typ = (item as Type); txtSource.Text = Language.GetSourceCode(typ, 0); } else if (item is MethodInfo) { txtSource.Text = Language.GetSourceCode(item as MethodInfo, 0); } } } }