Pergunta

Estou ocupado escrevendo um modelo CodeSmith que tem uma de suas propriedades como o tipo System.Type. Eu quero ser capaz de selecionar o tipo usando uma interface de usuário que escolhe a montagem, carrega o assembly e, em seguida, exibe os tipos que estão disponíveis em que a montagem. Posso, então, ir e escolher um dos tipos.

Alguém já encontrou ou código que faz isso ou algo semelhante escrito?

Foi útil?

Solução

Eu não tenho nada a mão, mas não é extremamente difícil de bater um up ... a maior pegadinha é a questão de não descarregar as DLLs ... mas um exemplo grosseiro:

(Isto usa o AssemblyQualifiedName corda, mas um Type funciona praticamente idêntica - apenas mudança sobre 3 linhas)

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);
        }
    }
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top