|
using System;
using System.Collections;
using System.Reflection;
using System.Windows.Forms;
namespace TenTec.Utils
{
/// <summary>
/// A class to get lists of members from assemblies using reflection
/// </summary>
internal class ReflectionPopulateManager
{
#region Fields
TreeView fTreeView;
Assembly[] fAssemblies;
static Hashtable fControlsAttached;
int fMaxLevel;
#endregion
#region Common
/// <summary>
/// Populates the specified tree view with the data from the
/// specified assemblies. The tree view is not populated at
/// once, it is populated "just in time" when it is needed.
/// </summary>
/// <param name="maxLevel">
/// Specify 0 if only namespaces should be displayed; 1 - if
/// only types.
/// </param>
public static void Attach(TreeView treeView, Assembly[] assemblies, DelegateFilterMember filter, int maxLevel, bool showReferencedAssemblies)
{
#region Check the arguments
if(treeView == null)
throw new ArgumentNullException("ManagerPopulateReflection.Attach(treeView)");
if(assemblies == null)
throw new ArgumentNullException("ManagerPopulateReflection.Attach(assemblies)");
if(assemblies.Length == 0)
throw new ArgumentException("ManagerPopulateReflection.Attach(assemblies)");
foreach(Assembly myAssembly in assemblies)
if(myAssembly == null)
throw new ArgumentException("ManagerPopulateReflection.Attach(assemblies)");
if(fControlsAttached != null && fControlsAttached.ContainsKey(treeView))
throw new Exception("ManagerPopulateReflection.Attach: The tree view has already been attached.");
#endregion
ReflectionPopulateManager myInstance = new ReflectionPopulateManager(treeView, assemblies, filter, maxLevel, showReferencedAssemblies);
AdjustControlsAttached();
fControlsAttached.Add(treeView, myInstance);
treeView.ImageList = HelpNodeImagesManager.ImageList;
}
/// <summary>
/// Cleans up the specified tree view and deattaches all the
/// event handlers attached in the Attach method.
/// </summary>
public static void Detach(TreeView treeView)
{
#region Check the arguments
if(treeView == null)
throw new ArgumentNullException("ManagerPopulateReflection.Detach(treeView)");
if(fControlsAttached == null || !fControlsAttached.ContainsKey(treeView))
throw new Exception("ManagerPopulateReflection.Detach: The tree view has not been attached.");
#endregion
treeView.Nodes.Clear();
treeView.BeforeExpand -= new TreeViewCancelEventHandler((fControlsAttached[treeView] as ReflectionPopulateManager).fTreeView_BeforeExpand);
treeView.ImageList = null;
fControlsAttached.Remove(treeView);
}
/// <summary>
/// Checks whether the fControlsAttached field initialized,
/// and initializes it if needed.
/// </summary>
private static void AdjustControlsAttached()
{
if (fControlsAttached == null)
fControlsAttached = new Hashtable();
}
/// <summary>
/// Creates a new instance of the ManagerPopulateReflection class.
/// </summary>
/// <param name="maxLevel">
/// Specify 0 if only namespaces should be displayed; 1 - if
/// only types.
/// </param>
private ReflectionPopulateManager(TreeView treeView, Assembly[] assemblies, DelegateFilterMember filter, int maxLevel, bool showReferencedAssemblies)
{
#region Check the arguments
if(treeView == null)
throw new ArgumentNullException("ManagerPopulateReflection.#ctor(treeView)");
if(assemblies == null)
throw new ArgumentNullException("ManagerPopulateReflection.#ctor(assemblies)");
if(assemblies.Length == 0)
throw new ArgumentException("ManagerPopulateReflection.#ctor(assemblies)");
foreach(Assembly myAssembly in assemblies)
if(myAssembly == null)
throw new ArgumentException("ManagerPopulateReflection.#ctor(assemblies)");
if(maxLevel < 0)
throw new ArgumentOutOfRangeException("ManagerPopulateReflection.#ctor(maxLevel)");
#endregion
#region Initialize fields
fTreeView = treeView;
fAssemblies = assemblies;
if(filter != null)
Filter += filter;
fMaxLevel = maxLevel;
#endregion
fTreeView.BeforeExpand += new TreeViewCancelEventHandler(fTreeView_BeforeExpand);
AddNamespaces(assemblies, showReferencedAssemblies);
}
/// <summary>
/// Adds namespace nodes to the tree view.
/// </summary>
private void AddNamespaces(Assembly[] assemblies, bool showReferencedAssemblies)
{
fTreeView.BeginUpdate();
#if !DEBUG
try
{
#endif
foreach(Assembly myAssembly in assemblies)
{
AddAssemblyNamespaces(myAssembly);
#region Process the referenced assemblies
if (showReferencedAssemblies)
{
AssemblyName[] myNames = myAssembly.GetReferencedAssemblies();
foreach (AssemblyName myName in myNames)
{
#if !DEBUG
try
{
#endif
AddAssemblyNamespaces(Assembly.Load(myName));
#if !DEBUG
}
catch(Exception ex)
{
MessagesManager.ShowError(fTreeView.FindForm(), ex.Message);
}
#endif
}
}
#endregion
}
#if !DEBUG
}
catch(Exception ex)
{
MessagesManager.ShowError(fTreeView.FindForm(), ex.Message);
}
finally
{
#endif
fTreeView.EndUpdate();
#if !DEBUG
}
#endif
}
/// <summary>
/// Adds namespace nodes to the tree view.
/// </summary>
private void AddAssemblyNamespaces(Assembly assembly)
{
Type[] myTypes = assembly.GetTypes();
for(int myIndexType = 0; myIndexType < myTypes.Length; myIndexType ++)
{
Type myType = myTypes[myIndexType];
if(ReflectionManager.IsExternal(myType))
{
if(Filter != null)
if(!Filter(myType))
continue;
string myNamespace = myType.Namespace;
if(GetNodeNamespace(myNamespace) == null)
AddNodeNamespace(myNamespace);
}
}
}
private void AddNodeNamespace(string @namespace)
{
TreeNode myNode = new TreeNodeReflectionMember(@namespace);
if (fMaxLevel > 0)
{
myNode.Tag = null;
myNode.Nodes.Add(string.Empty);
fTreeView.Nodes.Add(myNode);
}
}
private TreeNode GetNodeType(Type type)
{
TreeNode myNodeNamespace = GetNodeNamespace(type.Namespace);
if(myNodeNamespace == null)
return null;
for(int myIndexNode = myNodeNamespace.Nodes.Count-1; myIndexNode >= 0; myIndexNode--)
{
TreeNodeReflectionMember myNode = myNodeNamespace.Nodes[myIndexNode] as TreeNodeReflectionMember;
if(myNode != null && myNode.Member == type)
return myNode;
}
return null;
}
private TreeNode GetNodeNamespace(string @namespace)
{
@namespace = DisplayLabelManager.GetLabel(@namespace);
for(int myIndexNode = fTreeView.Nodes.Count-1; myIndexNode >= 0; myIndexNode--)
{
TreeNodeReflectionMember myNode = fTreeView.Nodes[myIndexNode] as TreeNodeReflectionMember;
if(myNode != null && myNode.NamespaceLabel == @namespace)
return myNode;
}
return null;
}
/// <summary>
/// Adds nodes for each of the types contained in the
/// specified namespace.
/// </summary>
private void AddNodesNamespaceTypes(TreeNodeReflectionMember node)
{
#region Check the arguments
if(node == null)
throw new ArgumentNullException("ManagerPopulateReflection.AddNodesNamespaceTypes(node)");
if(!node.IsNamespace)
throw new ArgumentException("ManagerPopulateReflection.AddNodesNamespaceTypes(node)");
#endregion
string myNamespace = DisplayLabelManager.GetNamespace(node.NamespaceLabel);
fTreeView.BeginUpdate();
node.Nodes.Clear();
try
{
foreach(Assembly myAssembly in fAssemblies)
{
AddNodesNamespaceTypes(node, myAssembly, myNamespace);
#region Process the references assemblies
AssemblyName[] myNames = myAssembly.GetReferencedAssemblies();
foreach(AssemblyName myName in myNames)
{
try
{
AddNodesNamespaceTypes(node, Assembly.Load(myName), myNamespace);
}
catch(Exception ex)
{
MessagesManager.ShowError(fTreeView.FindForm(), ex.Message);
}
}
#endregion
}
}
catch(Exception ex)
{
MessagesManager.ShowError(fTreeView.FindForm(), ex.Message);
}
finally
{
fTreeView.EndUpdate();
}
}
/// <summary>
/// Adds nodes for each of the types contained in the
/// specified namespace in the specified assembly.
/// </summary>
/// <param name="node">
/// The node which corresponds to the specified namespace.
/// </param>
private void AddNodesNamespaceTypes(TreeNode node, Assembly assembly, string @namespace)
{
foreach(Type myType in assembly.GetTypes())
{
if(ReflectionManager.IsExternal(myType))
{
if(Filter != null)
if(!Filter(myType))
continue;
if(myType.Namespace == @namespace)
{
if(GetNodeType(myType) != null)
continue;
TreeNode myNode = CreateNodeType(myType);
if(!ReflectionManager.IsDelegate(myType))
{
if(fMaxLevel > 1)
{
myNode.Tag = null;
myNode.Nodes.Add(string.Empty);
}
}
node.Nodes.Add(myNode);
}
}
}
}
private TreeNodeReflectionMember CreateNodeType(Type type)
{
return new TreeNodeReflectionMember(type);
}
private TreeNodeReflectionMember CreateNodeEvent(EventInfo @event)
{
return new TreeNodeReflectionMember(@event);
}
private TreeNodeReflectionMember CreateNodeField(FieldInfo field)
{
return new TreeNodeReflectionMember(field);
}
private TreeNodeReflectionMember CreateNodeMethod(MethodBase method)
{
return new TreeNodeReflectionMember(method);
}
private TreeNodeReflectionMember CreateNodeProp(PropertyInfo prop)
{
return new TreeNodeReflectionMember(prop);
}
private void AddNodesMemberMembers(TreeNodeReflectionMember node)
{
if(node == null)
throw new ArgumentNullException("ManagerPopulateReflection.AddNodesMemberMembers(node)");
if(!node.IsMember)
throw new ArgumentException("ManagerPopulateReflection.AddNodesMemberMembers(node)");
fTreeView.BeginUpdate();
node.Nodes.Clear();
try
{
Type myType = node.Member as Type;
if(myType != null)
AddNodesTypeMembers(node, myType);
}
catch(Exception ex)
{
MessagesManager.ShowError(fTreeView.FindForm(), ex.Message);
}
fTreeView.EndUpdate();
}
private void AddNodesTypeMembers(TreeNode node, Type type)
{
if(type == null)
throw new ArgumentNullException("ManagerPopulateReflection.AddNodesTypeMembers(node)");
MemberInfo[] myMembers = type.GetMembers(ReflectionManager.GetBindingFlags());
foreach(MemberInfo myMember in myMembers)
{
if(Filter != null)
if(!Filter(myMember))
continue;
ProjectNodeTypes myMemberType = ReflectionManager.GetMemberType(myMember);
TreeNodeReflectionMember myNode = null;
switch(myMemberType)
{
case ProjectNodeTypes.Event:
EventInfo myEvent = myMember as EventInfo;
if(ReflectionManager.IsExternal(myEvent))
myNode = CreateNodeEvent(myEvent);
break;
case ProjectNodeTypes.Field:
case ProjectNodeTypes.EnumField:
FieldInfo myField = myMember as FieldInfo;
if(ReflectionManager.IsExternal(myField))
myNode = CreateNodeField(myField);
break;
case ProjectNodeTypes.Method:
MethodBase myMethod = myMember as MethodBase;
if(ReflectionManager.IsExternal(myMethod))
{
myNode = CreateNodeMethod(myMethod);
myNode.Tag = null;
}
break;
case ProjectNodeTypes.Property:
PropertyInfo myProp = myMember as PropertyInfo;
if(ReflectionManager.IsExternal(myProp))
myNode = CreateNodeProp(myProp);
break;
}
if(myNode != null)
node.Nodes.Add(myNode);
}
}
private void fTreeView_BeforeExpand(object sender, System.Windows.Forms.TreeViewCancelEventArgs e)
{
if(e.Node.Tag != null)
return;
TreeNodeReflectionMember myNode = e.Node as TreeNodeReflectionMember;
if(myNode.IsNamespace)
AddNodesNamespaceTypes(myNode);
else if(myNode.IsMember)
AddNodesMemberMembers(myNode);
e.Node.Tag = true;
}
private DelegateFilterMember Filter;
#endregion
}
internal class TreeNodeReflectionMember: TreeNode
{
#region Fields
MemberInfo fMember;
string fNamespaceLabel;
#endregion
#region Methods
public TreeNodeReflectionMember(MemberInfo member)
{
if(member == null)
throw new ArgumentNullException("TreeNodeReflectionMember.#ctor(member)");
fMember = member;
bool myAddReflectedType = member.MemberType == System.Reflection.MemberTypes.NestedType;
Text = DisplayLabelManager.GetLabel(member, false, myAddReflectedType);
ImageIndex = SelectedImageIndex = HelpNodeImagesManager.GetProjectNodeTypeImageIndex(ReflectionManager.GetMemberType(member));
}
public TreeNodeReflectionMember(string @namespace)
{
fNamespaceLabel = DisplayLabelManager.GetLabel(@namespace);
Text = fNamespaceLabel;
ImageIndex = SelectedImageIndex = HelpNodeImagesManager.GetProjectNodeTypeImageIndex(ProjectNodeTypes.Namespace);
}
#endregion
#region Properties
public MemberInfo Member
{
get
{
return fMember;
}
}
public string NamespaceLabel
{
get
{
return fNamespaceLabel;
}
}
public bool IsNamespace
{
get
{
return fNamespaceLabel != null;
}
}
public bool IsMember
{
get
{
return fMember != null;
}
}
#endregion
}
internal delegate bool DelegateFilterMember(MemberInfo member);
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.