Question

Je suis en train d'écrire un modèle CodeSmith qui a une de ses propriétés que le type System.Type. Je veux être en mesure de choisir le type en utilisant une interface utilisateur qui prend l'ensemble, charge l'assemblage et affiche les types qui sont disponibles dans cette assemblée. Je peux ensuite aller chercher l'un des types.

Quelqu'un at-il rencontré ou écrit le code qui fait cela ou quelque chose de similaire?

Était-ce utile?

La solution

Je n'ai rien à la main, mais ce n'est pas extrêmement difficile à frapper un haut ... le plus grand Gotcha est la question de ne pas décharger les dll ... mais un exemple brut:

(celui-ci utilise la AssemblyQualifiedName chaîne, mais un Type fonctionne pratiquement identique - il suffit de changer environ 3 lignes)

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing.Design;
using System.Reflection;
using System.Windows.Forms;
using System.Windows.Forms.Design;

class MyData {
    [Editor(typeof(TypeTypeEditor), typeof(UITypeEditor))]
    [DisplayName("Some Type"), Description("Which type to use...")]
    public string SomeType { get; set; }

    [STAThread]
    static void Main() {
        Application.EnableVisualStyles();
        Application.Run(new Form {
            Controls = {
                new PropertyGrid { 
                    Dock = DockStyle.Fill,
                    SelectedObject = new MyData()
                }
            }
        });
    }
}

class TypeTypeEditor : UITypeEditor {
    public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context) {
        return UITypeEditorEditStyle.Modal;
    }
    public override object EditValue(ITypeDescriptorContext context, System.IServiceProvider provider, object value) {
        IWindowsFormsEditorService svc = provider == null ? null
            : provider.GetService(typeof(IWindowsFormsEditorService)) as IWindowsFormsEditorService;
        if (svc != null) {
            using(TypeForm form = new TypeForm()) {
                form.TypeName = Convert.ToString(value);
                if (svc.ShowDialog(form) == DialogResult.OK) {
                    value = form.TypeName;
                }
            }
        }
        return value;
    }
}
class TypeForm : Form {
    public string TypeName { get; set; }
    Button ok, load;
    TreeView tree;
    public TypeForm() {
        Text = "Select type";
        ok = new Button { Text = "OK" };
        ok.Enabled = false;
        ok.DialogResult = DialogResult.OK;
        load = new Button { Text = "Load..." };
        load.Dock = ok.Dock = DockStyle.Bottom;
        this.AcceptButton = ok;
        tree = new TreeView();
        tree.Dock = DockStyle.Fill;
        load.Click += load_Click;
        Controls.Add(load);
        Controls.Add(ok);
        Controls.Add(tree);
        tree.AfterSelect += tree_AfterSelect;
    }

    void tree_AfterSelect(object sender, TreeViewEventArgs e) {
        ok.Enabled = false;
        if (e.Node != null && e.Node.Tag != null) {
            string s = Convert.ToString(e.Node.Tag);
            if (!string.IsNullOrEmpty(s)) {
                TypeName = s;
                ok.Enabled = true;
            }            
        }
    }

    void load_Click(object sender, EventArgs e) {
        try {
            string path = null;
            using (OpenFileDialog dlg = new OpenFileDialog()) {
                dlg.Filter = "dll|*.dll|exe|*.exe";
                if (dlg.ShowDialog(this) == DialogResult.OK) {
                    path = dlg.FileName;
                }
            }
            if (!string.IsNullOrEmpty(path)) {
                Assembly asm = Assembly.LoadFrom(path);
                SortedList<string, TreeNode> namespaces = new SortedList<string, TreeNode>();
                foreach (Type type in asm.GetTypes()) {
                    if (!type.IsPublic) continue;
                    TreeNode nsNode;
                    if (!namespaces.TryGetValue(type.Namespace, out nsNode)) {
                        nsNode = new TreeNode(type.Namespace);
                        namespaces.Add(type.Namespace, nsNode);
                    }
                    nsNode.Nodes.Add(type.Name).Tag = type.AssemblyQualifiedName;
                }
                tree.BeginUpdate();
                tree.Nodes.Clear();
                try {
                    foreach (TreeNode node in namespaces.Values) {
                        tree.Nodes.Add(node);
                    }
                }
                finally {
                    tree.EndUpdate();
                }
            }
        }
        catch (Exception ex) {
            MessageBox.Show(this, ex.Message, ex.GetType().Name, MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
    }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top