Click here to Skip to main content
15,892,746 members
Articles / Programming Languages / C#

Demonstrating Custom Attributes: Build An Assembly Searching Tool.

Rate me:
Please Sign up or sign in to vote.
4.56/5 (10 votes)
25 Dec 2005CPOL32 min read 49.7K   332   39  
Build an assembly searching system via custom attributes and reflection.
using System;
using AssemblyFilesListerNamespace;
using DirectoryListerInterfaceNamespace;
using KeywordAttributeNamespace;
using System.Reflection;
using System.Collections;

namespace KeywordAttributeAssemblyLister
{
	// Structure that holds information about a 
	// type that is keyword attributed.
	public struct KeywordAttributedType
	{
		public string	m_TypeName;
		public int		m_iRelevance;
	}

	// Structure that holds information about an
	// assembly that is keyword attributed.
	public struct KeywordAttributedAssembly
	{
		public string		m_strAssemblyFullPath;
		public string		m_strKeyword;
		public ArrayList	m_KeywordAttributedTypesArray;
	}

	/// <summary>
	/// Summary description for ClassMain.
	/// </summary>
	class ClassMain
	{
		/// <summary>
		/// The main entry point for the application.
		/// </summary>
		[STAThread]
		static void Main(string[] args)
		{
			// We make use of the services of an IDirectoryLister interface implemented 
			// by the AssemblyFilesLister class.
			IDirectoryLister	dl = new AssemblyFilesLister();
			// The "dl" DirectoryLister object will return to us a DirectoryEntry object
			// filled with sub-directories and files contained inside a target directory.
			DirectoryEntry		de;
			// KeywordAttributedAssembliesArray is an ArrayList object which holds
			// an array of KeywordAttributedAssembly entries. Each entry represents
			// an assembly that uses the specified Keyword Attribute.
			ArrayList			KeywordAttributedAssembliesArray = new ArrayList();
			int					i = 0;

			// Indicate to the IDirectoryLister object which directory to scan.
			// In our case, this will be the directory supplied by the user in 
			// the first argument to this program.
			dl.DirectoryToList = args[0];
			// Indicate that we want the directory scanning to be recursive.
			dl.Recursive = true;
			// Tell the IDirectoryLister object to begin scanning.
			dl.BeginListing();

			// At this point, directory scanning is done and we obtain the main directory entry object.
			de = dl.DirectoryEntry;

			Console.WriteLine("Searching [{0}] for Assemblies Attributed with Keyword \"{1}\" and Minimum Relevance {2}.", args[0], args[1], args[2]);
			Console.WriteLine();

			// Search through the main directory and all its subdirectories and scan for 
			// Keyword Attributed Assemblies.
			SearchAndCollectKeywordAttributesAssemblies(de, args[1], Convert.ToInt32(args[2]), ref KeywordAttributedAssembliesArray);

			// Once done, KeywordAttributedAssembliesArray will contain KeywordAttributedAssembly objects
			// each of which contains information on one assembly that uses the specified Keyword Attribute.
			for (i = 0; i < KeywordAttributedAssembliesArray.Count; i++)
			{
				KeywordAttributedAssembly keyword_attributed_assembly = (KeywordAttributedAssembly)(KeywordAttributedAssembliesArray[i]);

				Console.WriteLine("Listing Types in Assembly : [{0}]", keyword_attributed_assembly.m_strAssemblyFullPath);

				// Each keyword_attributed_assembly contains an internal array of KeywordAttributedType
				// objects. Each object contains information on a type that uses the specified Keyword Attribute.
				// The relevance level is also included.
				int j = 0;
				for (j = 0; j < keyword_attributed_assembly.m_KeywordAttributedTypesArray.Count; j++)
				{
					KeywordAttributedType keyword_attributed_type = (KeywordAttributedType)(keyword_attributed_assembly.m_KeywordAttributedTypesArray[j]);

					Console.WriteLine("Type Name : {0}. Relevance : {1}.", keyword_attributed_type.m_TypeName, keyword_attributed_type.m_iRelevance);
				}

				Console.WriteLine();
			}
		}

		// This function searches through the files contained in the m_feArray of an input
		// DirectoryEntry struct searching for types which are KeywordAttributed by a 
		// specific keyword string and are above a minimum relevance value.
		// 
		// This function also recursively calls itself on all the directories contained
		// inside the m_deArray array of the input DirectoryEntry struct.
		static void SearchAndCollectKeywordAttributesAssemblies(DirectoryEntry de, string strKeyword, int iMinRelevance, ref ArrayList KeywordAttributedAssembliesArray)
		{
			if (de.m_feArray != null)
			{
				foreach(FileEntry fe in de.m_feArray)
				{
					CollectKeywordAttributedTypes(fe.m_strName, strKeyword, iMinRelevance, ref KeywordAttributedAssembliesArray);
				}
			}

			if (de.m_deArray != null)
			{
				foreach(DirectoryEntry _de in de.m_deArray)
				{
					SearchAndCollectKeywordAttributesAssemblies(_de, strKeyword, iMinRelevance, ref KeywordAttributedAssembliesArray);
				}
			}
		}

		static void CollectKeywordAttributedTypes(string strAssembly, string strKeyword, int iMinRelevance, ref ArrayList KeywordAttributedAssembliesArray)
		{
			Assembly assembly;

			try
			{
				// Load the assembly from a filename
				assembly = Assembly.LoadFrom(strAssembly);
			}
			catch (Exception)
			{
				// Could not load the assembly.
				return;
			}

			try
			{
				KeywordAttributedAssembly	current_keyword_attributed_assembly = new KeywordAttributedAssembly();
				bool						bAddToKeywordAttributedAssembliesArray = false;

				// Prepare a new AssemblyWithKeyword object in case we are indeed 
				// currently working with an Assembly that uses the Keyword attribute.
				current_keyword_attributed_assembly.m_strAssemblyFullPath = strAssembly;
				current_keyword_attributed_assembly.m_strKeyword = strKeyword;
				current_keyword_attributed_assembly.m_KeywordAttributedTypesArray = new ArrayList();

				// Collect all the Keyword Attrbutes from the Assembly itself.
				// Check for the KeywordAttribute on the Assembly itself.
				KeywordAttribute[] keyword_attributes_in_assembly = (KeywordAttribute[])(assembly.GetCustomAttributes(typeof(KeywordAttribute), true));
				// The collection is non-zero in size.
				if (keyword_attributes_in_assembly.Length > 0)
				{
					// We enumerate through the Keyword Attributes in the assembly.
					foreach (KeywordAttribute a in keyword_attributes_in_assembly)
					{
						// We filter through the keyword attributes and select
						// only those whose keywords match the search keyword (strKeyword)
						// and whose relevance is at least equal to the required 
						// relevance (i.e. iMinRelevance).
						if ((a.Keyword == strKeyword) && (a.Relevance >= iMinRelevance))
						{
							KeywordAttributedType keyword_attributed_type = new KeywordAttributedType();

							keyword_attributed_type.m_TypeName = "assembly";
							keyword_attributed_type.m_iRelevance = a.Relevance;

							// Add the current TypeWithKeyword object to the ArrayList
							// of TypeWithKeyword objects in the Current AssemblyWithKeyword 
							// object (current_assembly_with_keyword).
							current_keyword_attributed_assembly.m_KeywordAttributedTypesArray.Add((object)keyword_attributed_type);

							// Indicate that the Current AssemblyWithKeyword object (current_assembly_with_keyword)
							// is to be added to the input reference ArrayList AssemblyWithKeywordArray later on.
							bAddToKeywordAttributedAssembliesArray = true;
						}
					}
				}

				// Enumerate over the types in the current assembly and search for the 
				// occurrence of the usage of the Keyword Attribute.
				foreach (Type t in assembly.GetTypes())
				{
					// Check for the KeywordAttribute on the type
					KeywordAttribute[] keyword_attributes_in_types = (KeywordAttribute[])(t.GetCustomAttributes(typeof(KeywordAttribute), true));

					if (keyword_attributes_in_types.Length > 0)
					{
						foreach (KeywordAttribute a in keyword_attributes_in_types)
						{
							if ((a.Keyword == strKeyword) && (a.Relevance >= iMinRelevance))
							{
								KeywordAttributedType keyword_attributed_type = new KeywordAttributedType();

								keyword_attributed_type.m_TypeName = t.ToString();
								keyword_attributed_type.m_iRelevance = a.Relevance;

								current_keyword_attributed_assembly.m_KeywordAttributedTypesArray.Add((object)keyword_attributed_type);

								bAddToKeywordAttributedAssembliesArray = true;
							}
						}
					}

					// Enumerate over the members of the current type
					foreach (MemberInfo member in t.GetMembers())
					{
						// Check for the KeywordAttribute on the member
						KeywordAttribute[] keyword_attributes_in_type_members = (KeywordAttribute [])(member.GetCustomAttributes(typeof(KeywordAttribute), true));

						if (keyword_attributes_in_type_members.Length > 0)
						{
							foreach (KeywordAttribute a in keyword_attributes_in_type_members)
							{
								if ((a.Keyword == strKeyword) && (a.Relevance >= iMinRelevance))
								{
									KeywordAttributedType keyword_attributed_type = new KeywordAttributedType();

									keyword_attributed_type.m_TypeName = t.ToString() + "." + member.Name;
									keyword_attributed_type.m_iRelevance = a.Relevance;

									current_keyword_attributed_assembly.m_KeywordAttributedTypesArray.Add((object)keyword_attributed_type);

									bAddToKeywordAttributedAssembliesArray = true;
								}
							}
						}

						// If the current member is a method, we determine if any of the
						// method's parameters is also Keyword Attributed.
						if (member.MemberType == MemberTypes.Method)
						{
							MethodInfo mi = (MethodInfo)member;

							foreach(ParameterInfo p in mi.GetParameters())
							{
								KeywordAttribute[] keyword_attributes_in_method_parameters = (KeywordAttribute [])(p.GetCustomAttributes(typeof(KeywordAttribute), true));

								if (keyword_attributes_in_method_parameters.Length > 0)
								{
									foreach (KeywordAttribute a in keyword_attributes_in_method_parameters)
									{
										if ((a.Keyword == strKeyword) && (a.Relevance >= iMinRelevance))
										{
											KeywordAttributedType keyword_attributed_type = new KeywordAttributedType();

											keyword_attributed_type.m_TypeName = "Parameter to Method " + member.Name + "() : " + p.Name;
											keyword_attributed_type.m_iRelevance = a.Relevance;

											current_keyword_attributed_assembly.m_KeywordAttributedTypesArray.Add((object)keyword_attributed_type);

											bAddToKeywordAttributedAssembliesArray = true;
										}
									}
								}
							}
						}
					}
				}

				if (bAddToKeywordAttributedAssembliesArray)
				{
					KeywordAttributedAssembliesArray.Add((object)current_keyword_attributed_assembly);
				}
			}
			catch (Exception)
			{
			}
		}
	}
}

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.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Systems Engineer NEC
Singapore Singapore
Lim Bio Liong is a Specialist at a leading Software House in Singapore.

Bio has been in software development for over 10 years. He specialises in C/C++ programming and Windows software development.

Bio has also done device-driver development and enjoys low-level programming. Bio has recently picked up C# programming and has been researching in this area.

Comments and Discussions