23.8 Searching Assemblies Using Custom Search Techniques

 <  Day Day Up  >  

You want more control when searching by using a custom search for assembly type information.


Technique

The last recipe demonstrated how to specify flags to control the information returned when calling various reflection methods . Custom searching allows you to control what gets returned based on a custom criteria algorithm that you define. Custom searching involves the FindMembers method defined within the Type class. In addition to MemberTypes and BindingFlags values used within the first two parameters, a MemberFilter delegate is used as a callback for each found member, allowing you to determine whether it fits your necessary criteria. The MemberFilter delegate uses a MemberInfo object and a second parameter that contains the custom search information you designate . This object is passed into the FindMembers method as the last parameter. Within the delegate, use the MemberInfo object along with the object data you created to determine whether the member fits the specified criteria. Returning true from the delegate means a match was successful.

Listing 23.4 shows an application called asmgrep , although it doesn't purport to achieve the immense functionality of the UNIX grep utility. The object used as filter criteria is obtained on the command line and is placed within an ArrayList . It represents a list of strings to search for. If any Type or any Type 's corresponding members are the same as one of the values in the ArrayList , a successful match is made.

Listing 23.4 Searching for Types Using Custom Searching
 using System; using System.Reflection; using System.IO; using System.Collections; namespace _8_CustomSearch {     class Class1     {         [STAThread]         static int Main(string[] args)         {             if( args.Length <= 1 )                 return ShowUsage();             ArrayList filterStrings = new ArrayList();             // copy search strings to an array             for( int i = 1; i < args.Length; i++ )                 filterStrings.Add(args[i]);             // load assembly referenced in first cmd line arg             Assembly asm = Assembly.LoadFile( args[0] );             if( asm == null )             {                 return ShowUsage();             }             // create the member filter delegate             MemberFilter filter = new MemberFilter( OnCustomSearch );             foreach( Module module in asm.GetModules() )             {                 // enumerate through all types and search each member                 foreach( Type t in module.GetTypes() )                 {                     // first check to see if the type name matches                     if( filterStrings.Contains( t.Name ) )                         Console.WriteLine( "Found type {0}", t.Name );                     MemberInfo[] foundMembers = t.FindMembers( MemberTypes.All,                      BindingFlags.Public  BindingFlags.NonPublic                       BindingFlags.Static  BindingFlags.Instance                       BindingFlags.DeclaredOnly,                         filter, filterStrings );                     foreach( MemberInfo member in foundMembers )                     {                         Console.WriteLine( "Found member {0} which is a {1}" +                          " defined in {2}.", member.Name, member.MemberType,                          t.Name );                     }                 }             }             return 0;         }         public static bool OnCustomSearch( MemberInfo member, object filter )         {             // does the member name equal a string in the filter?             ArrayList al = (ArrayList) filter;             if( al.Contains( member.Name ))                 return true;             // check the member type also             if( al.Contains( member.MemberType ))                 return true;             return false;         }         static int ShowUsage()         {             Console.WriteLine( "asmgrep <assemblyname> <string 1 string 2" +              " ... string n>\n" );             return -1;         }     } } 

Comments

Using BindingFlags lets you customize a search to a great degree. However, the search only allows you to inspect certain attributes about a member. Custom searching allows you to create a custom search using specific search criteria that can key off any other property information contained in the MemberInfo class. In the preceding example, the key was the Name property and the Type property, with the search criteria being a list of strings that determine equality. Another example could be to key off the DeclaringType property to determine the members that are declared as members of a certain type, allowing you to narrow the member information to the members supported by a certain class for instance.

The example for this recipe demonstrates yet another useful application of reflection. Although it doesn't support the advanced feature set of a real grep utility, it does lay the necessary framework to create such an application. To further refine the application, allow it to search all the assemblies contained within the Global Assembly Cache. Additionally, allow regular expressions on the command line as search criteria. If you do these things, you will have an application that lets you quickly determine the appropriate assembly a given type is defined in, which is valuable when adding assembly references to a project. If you are so inclined to follow up and make these additions, send us a copy, will you?

 <  Day Day Up  >  


Microsoft Visual C# .Net 2003
Microsoft Visual C *. NET 2003 development skills Daquan
ISBN: 7508427505
EAN: 2147483647
Year: 2003
Pages: 440

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net