Recipe9.7.An Advanced Interface Search Mechanism


Recipe 9.7. An Advanced Interface Search Mechanism

Problem

You are searching for an interface using the Type class. However, complex interface searches are not available through the GetInterface and GetInterfaces methods of a Type object. The GetInterface method searches for an interface only by name (using a case-sensitive or case-insensitive search), and the GetInterfaces method returns an array of all the interfaces implemented on a particular type. You want a more focused searching mechanism that might involve searching for interfaces that define a method with a specific signature or implemented interfaces that are loaded from the GAC. You need more flexible and more advanced searching for interfaces that does not involve creating your own interface search engine. This capability might be used for applications like a code generator or reverse engineering tool.

Solution

The FindInterfaces method of a Type object can be used along with a callback to perform complex searches of interfaces on a type. The method shown in Example 9-8 will call a custom interface searching method, SearchInterfacesOfType.

Example 9-8. Performing complex searches of interfaces on a type

 using System;  using System.Reflection; public class SearchType {     public void FindSpecificInterfaces( )     {         Type[] types = new Type[3] {Type.GetType("System.ICloneable"),                        Type.GetType("System.Collections.ICollection"),                        Type.GetType("System.IappdomainSetup")};         Type[] interfaces = SearchInterfacesOfType(Type.GetType(                             "System.Collections.ArrayList"), types);         if (interfaces.Length > 0)         {             Console.WriteLine("Matches found:");             for(int counter =0; counter < interfaces.Length; counter++)              {                  Console.WriteLine("\tIFace Name: " +                                    interfaces[counter].ToString( ));                  Console.WriteLine("\tIFace Base Type: " +                                    interfaces[counter].BaseType);                  foreach (object attr in                           interfaces[counter].GetCustomAttributes(false))                  {                      Console.WriteLine("\t\tIFace attr: " + attr.ToString( ));                  }             }         }         else         {             Console.WriteLine("\t\tNo matches found");         }     }     public static Type[] SearchInterfacesOfType(Type searchedType,                                     Type[] interfaceNames)     {         TypeFilter filter = new TypeFilter(InterfaceFilterCallback);         Type[] interfaces = searchedType.FindInterfaces(filter, interfaceNames);         return (interfaces);     }     public static bool InterfaceFilterCallback(Type type, object criteria)     {         foreach (Type interfaceName in (Type[])criteria)         {             if (type.IsInstanceOfType(interfaceName))             {                 return (true);             }         }         return (false);     } 

The FindSpecificInterfaces method searches for any of the three interface types contained in the Names array that are implemented by the System.Collections.ArrayList type.

The SearchInterfacesOfType method accepts a type (searchedType) on which to search for interfaces and an array of types (interfaceNames) that contains criteria for the search. For this method, the criterion is a Type array of interfaces. This method then calls the FindInterfaces method on the searchedType parameter, passing in a delegate and the Type array criteria of interfaces. (The delegate will be invoked for each interface found.) This method then returns an array of interface types that match the criterion.

The TypeFilter delegate, filter, defines the IfaceFilterCallback method to be called for each interface found on the searchedType object. The real power of this search mechanism lies in the IfaceFilterCallback callback method.

This callback searches for each of the interface types in the criteria array that is implemented by the searchedType parameter of the SearchInterfacesOfType method.

Discussion

The FindInterfaces method of a Type object makes use of the TypeFilter delegate, which is passed to the filter parameter. This delegate is supplied by the FCL and allows an extra layer of filtering (of any type that you want) to occur. This delegate returns a Boolean value, where true indicates that the ifaceType object passed to this delegate should be included in the Type array that the FindInterfaces method returns; false indicates that this ifaceType object should not be included.

The FindInterfaces method will take into account all interfaces implemented by the type being searched as well as all of its base types when performing a search. In addition, if any of the interfaces implemented by any of these types also implements one or more interfaces, those interfaces are included in the search.


There are many ways to use this TypeFilter delegate to search for interfaces implemented on a typehere are just a few other searches that can be performed:

  • A filter to search for all implemented interfaces that are defined within a particular namespace (in this case, the System.Collections namespace):

     public bool IfaceFilterCallback(Type type, object criteria) {     return (type.Namespace == "System.Collections"); } 

  • A filter to search for all implemented interfaces that contain a method called Add, which returns an Int32 value:

     public bool IfaceFilterCallback(Type type, object criteria) {     MethodInfo mi = type.GetMethod("Add");     if (mi != null &&         mi.ReturnType == Type.GetType("System.Int32"))     {         return (true);     }     else     {         return (false);     } } 

  • A filter to search for all implemented interfaces that are loaded from the GAC:

     public bool IfaceFilterCallback(Type type, object criteria) {     if (type.Assembly.GlobalAssemblyCache)     {         return (true);     }     else     {         return (false);     } } 

  • A filter to search for all implemented interfaces that are defined within an assembly with the version number 1.0.3300.0:

     public bool IfaceFilterCallback(Type type, object criteria) {     if (type.Assembly.FullName.IndexOf("Version=1.0.3300.0") >= 0)      {         return (true);     }     else     {         return (false);     } } 

See Also

See Recipe 9.8; see the "Delegate Class" and "Type.FindInterfaces Method" topics in the MSDN documentation.



C# Cookbook
Secure Programming Cookbook for C and C++: Recipes for Cryptography, Authentication, Input Validation & More
ISBN: 0596003943
EAN: 2147483647
Year: 2004
Pages: 424

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