2009-08-19 28 views
2

Je suis occupé à écrire un modèle CodeSmith dont l'une de ses propriétés est de type System.Type. Je veux être en mesure de sélectionner le type à l'aide d'une interface utilisateur qui sélectionne l'assembly, charge l'assembly et affiche les types disponibles dans cet assembly. Je peux alors aller et choisir l'un des types.N'importe qui a un UITypeEditor qui sélectionne les instances System.Type?

Est-ce que quelqu'un a rencontré ou écrit du code qui fait ceci ou quelque chose de similaire?

Répondre

3

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 chaîne AssemblyQualifiedName, 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); 
     } 
    } 
}